Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > помогите разобраться с деревом


Автор: mrKoddy 13.6.2005, 21:31
У меня на форме лежит TTreeView1.
Пример.Я создаю потомок от TTreeView.
Код

//---------------------------------------------------------------------------
#ifndef ASBH
#define ASBH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------

class TASB : public TTreeView
{
public:
AnsiString Caption;
  __fastcall TASB(TComponent* AOwner);
};
//---------------------------------------------------------------------------
#endif
 __fastcall TASB::TASB(TComponent* Owner)
    : TTreeView(Owner)
{
}

Т.е. этот потомок тоже TTreeView только с доп "свойствами".Переопределенных медотов не будет наверное.
TASB у меня будет заполняться.Потом надо информацию из TTreeView1 "перекопировать" в TASB. т.е. заполнить "недостающие ствойства".
Вопросы:
1. Как "перекопировать"? По одному свойству копировать как-то не очень хочется. Да и если честно, то я не знаю какие именно надо будет копировать(индексы и уровни тока знаю что надо будет).Посему хотелось бы все скопом перекопировать.
2. Свойство Caption, приведенное выше должно присутствовать в каждом Item'е любого уровня.Куда его вписать?
3. Свойства TASB(родыне и от TTreeView) надо записать в файл. Но записать не текстом, а аброкодаброй.Так можно сделать или все же текстом писать надо будет?(вопрос глупый конечно).Потом прочитать из файла и восстановить дерево. Тоже самое проделать с TTeeView1.
PS:TASB на форме не отображается.Мне он там не нужен.

Автор: Vyacheslav 14.6.2005, 10:33
Цитата(mrKoddy @ 13.6.2005, 21:31)
1. Как "перекопировать"? По одному свойству копировать как-то не очень хочется. Да и если честно, то я не знаю какие именно надо будет копировать(индексы и уровни тока знаю что надо будет).Посему хотелось бы все скопом перекопировать.

Что значит "перекопировать"? Копировать или отнаследовать. Если обеспечить копирование объекта TTree в TASB, то переопределить метод Assign. Если отнаследовать - то стандартно как положени в С++

Автор: mrKoddy 14.6.2005, 19:53
Цитата
Что значит "перекопировать"?

Ну если упростить, то b=a
Цитата
Если обеспечить копирование объекта TTree в TASB, то переопределить метод Assign.

А можно поподробнее?
А как на счет остальных вопросов?

Автор: Vyacheslav 15.6.2005, 09:34
В общем даже и переопределение не понадобится

Код

TASB* asb = new TASB(this);
           asb->Assign(MyTree);           
....
MyTree->Assign(asb);           




Цитата(mrKoddy @ 14.6.2005, 19:53)
А как на счет остальных вопросов?

С Caption - непонятно. TreeView использует в качестве Item объекты TTreeNode, который имеют свойство Text. Оно имеется независимо от уровня.

По третьему вопросу так просто не объяснишь. Для начала вот это прочтите
http://bcdev.narod.ru/Articles/Saving_and_loading_components.htm


Автор: mrKoddy 15.6.2005, 19:42
Цитата
В общем даже и переопределение не понадобится

Спасибо, попробую.
Цитата
С Caption - непонятно. TreeView использует в качестве Item объекты TTreeNode, который имеют свойство Text. Оно имеется независимо от уровня.

Ну вот типа Text мне и надо еще пару свойств.
Цитата
По третьему вопросу так просто не объяснишь. Для начала вот это прочтите

Это я уже читал. Правда пока в подробности не вдавался.

Автор: Vyacheslav 16.6.2005, 10:24
Цитата(mrKoddy @ 15.6.2005, 19:42)

Ну вот типа Text мне и надо еще пару свойств.


Ну тогда Вам потребуется производый класс от TTreeNode как минимум, и возможно свои TTreeNodes и TTreeView smile Не прще ли для хранения дополнительной информации воспользоваться специально предназначенным для этих целей свойсвом TTreeNode::Data

Автор: mrKoddy 16.6.2005, 19:35
Цитата
Не прще ли для хранения дополнительной информации воспользоваться специально предназначенным для этих целей свойсвом TTreeNode::Data

Да, проще. Только я все же не понял, как по предложенной выше ссылке сохранять/загружать компонент. Сохранить получилось. А вот загрузить не очень. Загрулил. Но как только я кликаю по ветке, что б раскрылась, у меня сразу AV вылетает. Как я понял из статьи надо что-то сделать перед загрузкой. А вот что и как не понял.

Автор: Vyacheslav 17.6.2005, 10:42
Смотреть конкретно надо. Так не скажешь, что не так
Вот код создает записывает в файл, а потом создает копию TTreeView рядом с оригиналом
Код

void __fastcall TForm1::Button4Click(TObject *Sender)
{

  {
    std::auto_ptr<TFileStream> ofs( new TFileStream("test", fmCreate));
    std::auto_ptr<TWriter> Writer( new TWriter(ofs.get(), 4096));
    Writer->Root = this;
    Writer->WriteComponent(TreeView1);
  }
 
  std::auto_ptr<TFileStream> ifs(new TFileStream("test", fmOpenRead));
  std::auto_ptr<TReader> Reader(new TReader(ifs.get(), 4096));
  TComponent* Component = NULL;
  Reader->Parent = this;
  TreeView1->Name = "TreeView2";
  // load the stored component
  TTreeView* NewTree = new TTreeView(this);
  Reader->BeginReferences();
  try {
    NewTree = (TTreeView*)Reader->ReadComponent(NewTree);
  }
  __finally {
    Reader->FixupReferences();
    Reader->EndReferences();
  }

  NewTree->Left +=  NewTree->Width + 10;
}

Автор: mrKoddy 17.6.2005, 19:56
У меня на форме TreeView1 уже лежит т.к. я его положил через дизайнер. Наверное поэтому возникает проблема.
Загружается у меня вот так:
Код

LoadComponent("C:\\TreeView1.component",TreeView1);

Записывается так:
Код

SaveComponent("C:\\TreeView1.component",TreeView1); 

Можно попробовать сделать по аналогии - TreeView1 скрыть(если получиться - удалть, хотя я в этом сомневаюсь).
Динамически создать TreeView2 и потом уже
Код

LoadComponent("C:\\TreeView1.component",TreeView2);

Но мне такое кол-во манипуляций не очень нравиться. smile К тому же я не уверен, что это заработает.

Автор: mrKoddy 29.6.2005, 20:37
Воспользовался кодом Vyacheslav'a
Разбил его на сохранение и загрузко компанента.
Делал почти по спавке:
Код

TTreeView1 *NewTree;
typedef struct MyRec
{
  AnsiString Caption, Icon,Command,Parameters,Work_dir;
  int Window;
} TMyRec;
typedef TMyRec* PMyRec;
PMyRec  MyRecPtr;
MyRecPtr->Caption = "Caption";
// и т.д.
TreeView1->Items->AddChildObject(TreeView1->Selected,"Item", MyRecPtr);
//сохранение компонента 
    std::auto_ptr<TFileStream> ofs( new TFileStream("test", fmCreate));
    std::auto_ptr<TWriter> Writer( new TWriter(ofs.get(), 4096));
    Writer->Root = this;
    Writer->WriteComponent(TreeView1);
//что-то делается
//загрузка компонента
std::auto_ptr<TFileStream> ifs(new TFileStream("test", fmOpenRead));
  std::auto_ptr<TReader> Reader(new TReader(ifs.get(), 4096));
  TComponent* Component = NULL;
  Reader->Parent = this;
  TreeView1->Name = "TreeView2";
  // load the stored component
  TTreeView* NewTree = new TTreeView(this);
  Reader->BeginReferences();
  try {
    NewTree = (TTreeView*)Reader->ReadComponent(NewTree);
  }
  __finally {
    Reader->FixupReferences();
    Reader->EndReferences();
  }

  NewTree->Left +=  NewTree->Width + 10;
PMyRec  MyRecPtr;
MyRecPtr = new TMyRec;
MyRecPtr =(MyRec*)NewTree->Selected->Data;
ShowMessage("Caption - " + MyRecPtr->Caption);

Сохранение и загрузка проходят нормально. Но вот заполнение структуры не происходит.Т.е. там пусто.
Если вместо заполнения структуры написать Cap=PMyRec(NewTree->Selected->Data)->Caption, как советует справка, то происходит AV.Такое ощущение, что дополнительная инфа в файл не сохраняется. Если файл через ТС посмотреть, то можно увидеть только названия двух итемов нулевого уровня(два корня).

Автор: chaos 5.7.2005, 09:41
Цитата(Vyacheslav @ 16.6.2005, 10:24)
Цитата(mrKoddy @ 15.6.2005, 19:42)

Ну вот типа Text мне и надо еще пару свойств.


Ну тогда Вам потребуется производый класс от TTreeNode как минимум, и возможно свои TTreeNodes и TTreeView smile Не прще ли для хранения дополнительной информации воспользоваться специально предназначенным для этих целей свойсвом TTreeNode::Data

извиняюсь что не в тему
а можн по подробнее про свойство data

Автор: Vyacheslav 5.7.2005, 10:45
Цитата(mrKoddy @ 29.6.2005, 20:37)
Такое ощущение, что дополнительная инфа в файл не сохраняется.

А с чего Вы взяли, что Data сохраняться? Это тип void * и что там может лежать в конкретный момент известно только одному богу и ... программисту.
К сожалению, создание своего класса-наследника от TTreeNode, для решения данной проблемы бесполезно, так как методы
Код

    void __fastcall WriteData(Classes::TStream* Stream, PNodeInfo Info);
    void __fastcall ReadData(Classes::TStream* Stream, PNodeInfo Info);

определены как невиртуальные плюс еще и размещены в секции private.

Так что проще пойти по пути отделения информации и интерфейса и сохранять и восстаналивать информацию по дереву отдельно от TTreeView

Автор: mrKoddy 5.7.2005, 19:18
Цитата
Так что проще пойти по пути отделения информации и интерфейса и сохранять и восстаналивать информацию по дереву отдельно от TTreeView

Все зависит от структуры дерева. smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)