C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
TreeView немного посложнее
** laifik
  Отправлено: 27.10.2003, 15:26


Не зарегистрирован







Уже второй день не могу сформировать дерево. Вроде все понятно, а как нужно, не получается. Кто сможет, помогите, пожалуйста!
Задача такая. схематично орисую структуру дерева:

Год
2002
Январь
Февраль
2003
Март
Июнь
Август
Сентярь
Понятно, что ступенчатая структура базы данных. Таблица года и таблица месяца связаны по ключу.
Сначала формирую корневой узел:
//Создание дерева"
int PrCount = TestModule->ADOGod->RecordCount;
TreeView1->Items->Clear(); //Очистка списка
TreeView1->Items->Add(NULL, "Год");

//Доавление дочерних узлов"Год"
TestModule->ADOGod->First();
do
{
for(int ii=0; ii AnsiString Pr=TestModule->ADOGod->FieldByName("God")->AsString;
TreeView1->Items->AddChild(TreeView1->Items->Item[0], Pr);
TestModule->ADOGod->Next();
}
}
while (TestModule->ADOGod->Eof!=TRUE);

Все работает правильно, создаются узлы 2002 и 2003.
Далее хотела сделать цикл в цикле.
int MesCount = TestModule->ADOMesaz->RecordCount;
Но MesCount меняется в зависимости от года. И вот в этом месте не могу додумать. Куда и как вставить этот цикл, чтоы работало правильно.
//Добавление дочерних узлов "Месяц"

TestModule->ADOMesaz->First();
do
{
for(int kk=0; kk AnsiString Ms=TestModule->ADOMesaz->FieldByName("Mesaz")->AsString;
TreeView1->Items->AddChild(TreeView1->Items->Item[????], Ms);
TestModule->ADOMesaz->Next();
}
}
while (TestModule->ADOMesaz->Eof!=TRUE);
И что должно стоять вместо вопросов. Если цикл в цикле, то туда ставлю ii. Но это, видимо, неправильно. Отзовитесь, кто создавал такое дерево. Заранее брагодарю!

ohmy.gif
Nick
Отправлено: 28.10.2003, 07:38


Машинист паровоза

Группа: Участник
Сообщений: 247



Я сделал так.

typedef struct { int kode; char RemarkText[255]; } tNodeData;

первый вызов процедуры

Parent_ID = 0;
item = NULL;

void __fastcall TFormMain::mLoadRepTree( int Parent_ID, TTreeNode *item )
{
TTreeNode *newItem = NULL;

char *RemarkText;
// IBQ_TempLoad — запрос выдает строки в порядке
// id parent_id Name
// 1 0 Год
// 2 1 2002
// 3 2 январь
// 4 2 февраль
// 5 2 ...
// 10 0 2003
// 11 10 январь

while ((IBQ_TempLoad->FieldByName("opParent_ID")->AsInteger == Parent_ID) &&
!IBQ_TempLoad->Eof )
{
tNodeData *NodeData = (tNodeData *)malloc(sizeof(tNodeData));
strcpy(NodeData->RemarkText, IBQ_TempLoad->FieldByName("opRemark")->AsString.c_str());
NodeData->kode = IBQ_TempLoad->FieldByName("opTree_ID")->AsInteger;

if ( item == NULL )
{
newItem = TV_Rep->Items->AddObject( newItem, IBQ_TempLoad->FieldByName("OPNAME")->AsString, NodeData );
}
else newItem = TV_Rep->Items->AddChildObject( item, IBQ_TempLoad->FieldByName("OPNAME")->AsString, NodeData );

int iParent_ID = IBQ_TempLoad->FieldByName("OPTREE_ID")->AsInteger;
IBQ_TempLoad->Next();
mLoadRepTree( iParent_ID, newItem ); // вызов этой же процедуры
// для листочков считанного узла
};
};
// набор данных создается процедурой
// тоже с рекурсивным вызовом FireBird
// в ADO придется писать записи по порядку
** laifik
  Отправлено: 28.10.2003, 11:23


Не зарегистрирован







К сожалению, мне трудно сейчас переключиться на совсем другую идею, тем более, я не представляю, что за задача была у Вас. Трудно понять из этого куска, что откуда берется. Я все мусолю свою идею. И вот что получается. Цикл в цикле, после формирования узла "2003" в корневом узле "Год" по ключу GodID в таблице месяцев ищутся соответствующие записи. Их количество подсчитывается и формируются новые дочерние узлы уже из перечня месяцев (TreeView1->Items->AddChild(TreeView1->Items->Item[ii+1], Ms)wink.gif. До этого момента все правильно.
Получается такая структура:
- Год

- 2003

+ Январь
Ноябрь

2004
Далее происходит непонятное. Когда делаю пошаговую отладку, все указатели идут правильно. А на деле при такой записи ii+1 месяцы, соответствующие 2004 прописались внутри Января. А нужно, чтобы "+" был около 2004 и внутри него были месяцы. Помогите, пожалуйста, добить этот вариант. Или на худой конец, хотелось бы почитать подробное объяснению по Вашему предложенному.

Код
//Добавление корневого узла"Год"

int PrCount = TestModule->ADOGod->RecordCount;

TestModule->ADOGod->First();
do
{
for(int ii=0; ii
AnsiString Pr=TestModule->ADOGod->FieldByName("God")->AsString;
int PrId=TestModule->ADOGod->FieldByName("GodID")->AsInteger;
TreeView1->Items->AddChild(TreeView1->Items->Item[0], Pr);

//Добавление дочернего узла "Месяц"

ffield = "GodID";
fvalue = PrId;
opts << loCaseInsensitive;
TestModule->ADOMesazShet->Locate(ffield, fvalue, opts);
int MesCount = TestModule->ADOMesaz->RecordCount;
Edit9->Text = MesCount;
do
{
for(int kk=0; kk AnsiString Ms=TestModule->ADOMesaz->FieldByName("Mesaz")->AsString;
TreeView1->Items->AddChild(TreeView1->Items->Item[ii+1], Ms);
TestModule->ADOMesaz->Next();
}
}
while (TestModule->ADOMesaz->Eof!=TRUE);

TestModule->ADOGod->Next();
}
}
while (TestModule->ADOGod->Eof!=TRUE);
** laifik
  Отправлено: 28.10.2003, 15:44


Не зарегистрирован







Все-таки мне помогли добить мой вариант. Может кому пригодится.
Код
//Создание "дерева"
int PrCount = TestModule->ADOGod->RecordCount;
TreeView1->Items->BeginUpdate();
TreeView1->Items->Clear(); //Очистка списка
TTreeNode *root = TreeView1->Items->AddChild( NULL, "Год" ); //root — Год

//Добавление узла"Год"
TestModule->ADOGod->First();
do
{
for(int ii=0; ii AnsiString Pr=TestModule->ADOGod->FieldByName("God")->AsString;
int PrId=TestModule->ADOGod->FieldByName("GodID")->AsInteger;
TTreeNode *cyear = TreeView1->Items->AddChild( root, Pr);

//Добавление дочернего узла "Месяц"

ffield = "GodID";
fvalue = PrId;
opts << loCaseInsensitive;
TestModule->ADOMesazShet->Locate(ffield, fvalue, opts);
int MesCount = TestModule->ADOMesaz->RecordCount;

Edit9->Text = MesCount;
do
{
for(int kk=0; kk AnsiString Ms=TestModule->ADOMesaz->FieldByName("Mesaz")->AsString;
TreeView1->Items->AddChild( cyear, Ms); //root — ãîä
TestModule->ADOMesaz->Next();
}
}
while (TestModule->ADOMesaz->Eof!=TRUE);

TestModule->ADOGod->Next();
}
}
while (TestModule->ADOGod->Eof!=TRUE);
TreeView1->Items->EndUpdate(); biggrin.gif
laifik
  Отправлено: 29.10.2003, 09:13


Дежурный стрелочник

Группа: Участник
Сообщений: 70



При отправке сообщения в for произошел сбой и выпали куски. Я их восстанавливаю:
for(int ii=0; ii AnsiString Pr=TestModule->ADOGod->FieldByName("God")->AsString;
и т.д.
и второй:
for(int kk=0; kk AnsiString Ms=TestModule->ADOMesaz->FieldByName("Mesaz")->AsString;
и т.д.
Обратите на это внимание.
ohmy.gif
laifik
Отправлено: 29.10.2003, 09:14


Дежурный стрелочник

Группа: Участник
Сообщений: 70



Какой-то заколдованный код. Попробую еще раз:
for(int kk=0; kk
AnsiString Ms=TestModule->ADOMesaz->FieldByName("Mesaz")->AsString; ohmy.gif
laifik
Отправлено: 29.10.2003, 09:18


Дежурный стрелочник

Группа: Участник
Сообщений: 70



Короче, дурдом какой-то. Впервые с таким сталкиваюсь. При просмотре сообщения все выглыдит нормально.
Смотрите ссылку на другой форум, там все правильно, хотя были такие же казусы.
http://www.progz.ru/viewtopic.php?t=4240
Георгий
Отправлено: 29.10.2003, 10:29


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



А ты тегом CODE попробуй воспользоваться

Вернуться в Вопросы программирования в C++Builder