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

 
TTreeView, обход
virt------------
Отправлено: 20.03.2007, 19:52


Ученик-кочегар

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



(с TTreeView мало знаком)
Проблема:
Структуру подгружаю из файла.
Для некоторых узлов нужно изменить картинки (Statelndex)
- Как мне пройти по всему дереву?
(По возможности пример)
desivers
Отправлено: 20.03.2007, 20:08


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

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



Есть свойство Count возвращает количество нодов
обратится к ноде по индексу можно так
TreeView->Items->Item[i]
пройтись можно в цикле

for (int i = 0; 0<= TreeView->Count; i++)
{
if (условие)
TreeView->Items->Item[i]->StateImage = 0;
}

Отредактировано desivers — 20.03.2007, 20:10
Ramzay
Отправлено: 20.03.2007, 21:26


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

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



Если емеешь дело с иерархической структурой (деревом), тебе без рекурсии не обойтись. Под рукой нет программы на BCB, но выглядит это приблизительно так:

1) Тебе нужно написать функцию (SetBranch), которая будет получать узел и для его подузлов будет устанавливать Statelndex.

2) После установки Statelndex функция вызывает сама себя с параметром "текущий подузел".

CODE


. . .
for(int i=0; i<TreView1->Items->Count; i++) // цикл перебора узлов самого верхнего уровня дерева
{
  if (условие)
     TreeView->Items->Item[i]->StateImage = 0;
  SetBranch(TreeView->Items->Item[i]);   // установить StateImage на подузлах узла TreeView->Items->Item[i]
}
. . .



//------------------------------------------------------------------------
// устанавливает StateImage на подузлах узла CurNode
//------------------------------------------------------------------------
SetBranch(TTreeNode* CurNode)  
{
 for (int i = 0; i< CurNode->Count; i++)  // перебирает подузлы узла CurNode
 {
   TTreeNode* CurSubNode   = CurNode->Item[i]; // текущий подузл узла  CurNode
   if (условие)
     CurSubNode->StateImage = 0; // делаем то, что нам нужно
  SetBranch(CurSubNode);              // установить StateImage на подузлах узла CurSubNode
 }

}


virt------------
Отправлено: 22.03.2007, 21:21


Ученик-кочегар

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



Спасибо!!!
[Только получилось выйти в инет...]

Еще пару вопросов
1) Я так понял в TreeView используется для каждого узла Имя и data
т.е. Имя <-> Data
...как при добовлении узла записать data (в частности значения типа int) и потом при нажатии на имя выводилась data?

2) Как создать узел в определенном месте...
т.е. вид пути к узлу "qwer\wer\qw" "Имя1"
Т.е. при создании разлаживаем "qwer\wer\qw" на три узла и создаем "Имя 1" — С этим проблем нет, но как быть если есть "qwer\wer\qw" "Имя2" при этом они не идут в подрят.
Т.е. нужно определить есть ли "qwer"
нет — создаем ... всё
есть- проверяем естли в нем "wer"
___ нет — создаем оставшееся
___ да-проверяем естли в нем "qw"
...
Т.е. по факту нужно найти родителя с именем, потом ребенка, потом опять ребенка...
Как это сделать?


desivers
Отправлено: 22.03.2007, 21:41


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

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



ЛОЛ. Только неделю назад реализовал подобное в дипломном, но зас хочу уйти от такой схемы.

вобщем смысыл такой я беру строку из БД разбираю ее, а дальще как ты написал разбирайся

CODE

void __fastcall TFormMain::NextLines()
{
AnsiString Buff = "", Path = "";
TTreeNode *FocusNode, *TempNode;
bool CreateNode = false, FirstWord = true;

Path = ADOQueryPrimaryPath->Value;

for (int i = 1; i <= Path.Length(); i++)
{
 if (Path[i] == '\\')
 {
  if (FirstWord == true)
  {
   TempNode = TreeView->Items->GetFirstNode();
   while (TempNode)
   {
    if (TempNode->Text == Buff)
    {
     FocusNode = TempNode;
     break;
    }
    TempNode = TempNode->getNextSibling();
   }
   if (!TempNode)
   {
    FocusNode = TreeView->Items->AddChild(NULL, Buff);
    CreateNode = true;
   }
   FirstWord = false;
  }
  else
  {
   if (CreateNode == true)
    FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
   else
   {
    if (FocusNode->Count == 0)
    {
     FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
     CreateNode = true;
    }
    else
    {
     TempNode = FocusNode->getFirstChild();
     while (TempNode)
     {
      if (TempNode->Text == Buff)
      {
       FocusNode = TempNode;
       break;
      }
      TempNode = TempNode->getNextSibling();
     }
     if (!TempNode)
     {
      FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
      CreateNode = true;
     }
    }
   }
  }
  Buff = "";
 }
 else
  Buff = Buff + Path[i];
}

if (ADOQueryPrimaryFolder->Value == true)
{
 if (FirstWord == true)
  TreeView->Items->AddChild(NULL, Buff);
 else
 {
  if (CreateNode == true)
   FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
  else
  {
   if (FocusNode->Count == 0)
   {
    FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
    CreateNode = true;
   }
   else
   {
    TempNode = FocusNode->getFirstChild();
    while (TempNode)
    {
     if (TempNode->Text == Buff)
     {
      FocusNode = TempNode;
      break;
     }
     TempNode = TempNode->getNextSibling();
    }
    if (!TempNode)
    {
     FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
     CreateNode = true;
    }
   }
  }
 }
}
else
{
 if (FirstWord == true)
 {
  FocusNode = TreeView->Items->AddChild(NULL, Buff);
  FocusNode->ImageIndex = 1;
  FocusNode->SelectedIndex = 1;
 }
 else
 {
  FocusNode = TreeView->Items->AddChild(FocusNode, Buff);
  FocusNode->ImageIndex = 1;
  FocusNode->SelectedIndex = 1;
 }
   }

FirstWord = true;
CreateNode = false;
Buff = "";
}
virt------------
Отправлено: 23.03.2007, 20:04


Ученик-кочегар

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



Спасибо
Ramzay
Отправлено: 23.03.2007, 20:22


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

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



QUOTE (virt------------ @ 22.03.2007, 21:21)
1) Я так понял в TreeView используется для каждого узла Имя и data
т.е. Имя <-> Data
...как при добовлении узла записать data (в частности значения типа int) и потом при нажатии на имя выводилась data?

Data имеет тип void* и является указателем на что-либо. Если ты хочешь поставить в соответствие узлу переменную int, то значению этого указателя нужно присвоить адрес int-переменной.
CODE


int aaa=10; // переменная типа int;
CurNode->Item[i]->Data=&aaa; //Присваиваем адрес переменной
int bbb = *((int*)CurNode->Item[i]->Data); // Переменная bbb получает заначение 10



С именем все намного проще. CurNode->Item[i]->Text="Этот текст будет виден на узле дерева";

Отредактировано Ramzay — 23.03.2007, 20:25

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