Помощь - Поиск - Пользователи - Календарь
Полная версия: Проблема с компонентом TreeView
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
ninja
Добрый день!

Необходимо заполниль дерево с помощью компонента TreeView, имя элемента дерева должно состоять из номеров и имен, т.е. например дерево должно выглядеть следующим образом:

Код
1имя1
2имя2
3имя3
   3.1имя4
   3.2имя5
      3.2.1имя6
4имя7
   4.1имя8


таким образом чтобы и дочерние и родительские элементы имели порядковый номер.
Столкнулся с такой проблемой что нумерация при добавлении дочернего элемента начинается с 0

Родительские элементы нумеруются нормально, а вот с дочерними проблема

void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString name, roditelb;
TTreeNode *node;

if (TreeView1->Items->Count == 0) // добавление первого элемента
{
name = "1:";
name += Edit1->Text+":";
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
TreeView1->Items->Add(NULL,name);
}
else
{
if (RadioGroup1->ItemIndex == 0) /// добавление родительских элементов
{
name = IntToStr(TreeView1->Items->Count+1)+":";
name += Edit1->Text+":";
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
TreeView1->Items->Add(NULL,name);
}

if (RadioGroup1->ItemIndex == 1) /// добавление дочерних элементов
{
selected2++;
name = IntToStr(selected2)+":";
name = Edit1->Text+":";
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
TreeView1->Items->AddChild(TreeView1->Selected,name);
}
}
}




Спасибо за помощь.
Client
name = IntToStr(selected2)+":";
name = Edit1->Text+":"; // тут опечатка у тебя? может по этому и не правильно?
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
ninja
Да действительно опечатка, но это всего лишь добаляет имя, тоесть у меня имя берется их 2х компонентов Edit и ComboBox, я просто уже поразному пробывал, текст был закоментирован, я не заметил, если исправить все равно не работает.
Client
присоедини весь проект, а то лень создавать самому smile.gif
volvo
А дочерние можно нумеровать, используя не selected2 (непонятно где и как описанный), а:

		if (RadioGroup1->ItemIndex == 1) /// добавление дочерних элементов
{
name = IntToStr(TreeView1->Selected->Count)+":";
name += Edit1->Text+":";
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
TreeView1->Items->AddChild(TreeView1->Selected,name);
}


TreeView1->Selected->Count вернет тебе количество дочерних элементов у Selected, не надо ничего считать вручную, все уже посчитано... Получить из Selected строку до двоеточия и добавить ее в начало нового элемента - не самая большая проблема, правда?
ninja
Вот проект:

Нажмите для просмотра прикрепленного файла

Владимир спасибо Вам огромное все прекрасно работает, как то я проглядел этот свойство у TreeView
ninja
Еще такой вопрос: как реализовать создание пунктов меню на основе полученного дерева? т.е Мне необходимо создать, используя компонент MainMenu, пункты меню, учитывая все уровни вложенности полученного дерева, не могу понять как мне это сделать.

получилось пока следующее:

TMenuItem *Menu;

for (i = 0; i < TreeView1->Items->Count; i++)
{
Menu = new TMenuItem(0);
Menu->Caption = "Пункт меню " + IntToStr(i+1);
MainMenu1->Items->Add(Menu);
}
volvo
Так лень мне Билдер запускать... Дельфи открытая, поэтому сделаю здесь (переносится на Билдер практически один в один)

procedure BuildMenu(node: TTreeNode; menu: TMenuItem);
var
NewMenu, NewSubMenu: TMenuItem;
TVnode: TTreeNode;
begin
TVnode := node;
while TVnode <> nil do
begin
if TVnode.HasChildren then
begin
NewSubMenu := TMenuItem.Create(menu);
NewSubMenu.Caption := TVnode.Text;
BuildMenu(TVnode.GetFirstChild, NewSubMenu);
menu.Add(NewSubMenu);
end
else
begin
NewMenu := TMenuItem.Create(menu);
NewMenu.Caption := TVnode.Text;
menu.Add(NewMenu);
end;
TVnode := TVnode.GetNextSibling;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var CurrMenu: TMainMenu;
begin
CurrMenu := TMainMenu.Create(Form1);
BuildMenu(TreeView1.Items.GetFirstNode, CurrMenu.Items);
Form1.Menu := CurrMenu;
end;
Вот и все...

Проверял до 5-го уровня вложенности - работает нормально...
ninja
Владимир спасибо, на делфи все отлично работает, я в Билдер перенес, но почему-то ничего не создается, вроде все проверил, по нажатию на кнопку никакой реакции....

void BuildMenu (TTreeNode *node, TMenuItem *menu)
{
TMenuItem *NewMenu, *NewSubMenu;
TTreeNode *TVnode;

TVnode = node;

while (TVnode != NULL)
{
if (TVnode->HasChildren)
{
// NewSubMenu = TMenuItem->Create(menu);

NewSubMenu = new TMenuItem(menu);
NewSubMenu->Caption = TVnode->Text;
BuildMenu(TVnode->getFirstChild(), NewSubMenu);
menu->Add(NewSubMenu);
}
else
{
//NewMenu := TMenuItem.Create(menu);

NewSubMenu = new TMenuItem(menu);
NewMenu->Caption = TVnode->Text;
menu->Add(NewMenu);
}
TVnode = TVnode->getNextSibling();
}
}


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

TMainMenu *CurrMenu;

CurrMenu = new TMainMenu(Form1);
BuildMenu(TreeView1->Items->GetFirstNode(), CurrMenu->Items);
Form1->Menu = CurrMenu;

}


volvo
Значит, плохо перевел:

void BuildMenu(TTreeNode *node, TMenuItem *menu)
{
TTreeNode *TVnode = node;
while(TVnode)
{
if(TVnode->HasChildren)
{
TMenuItem *NewSubMenu = new TMenuItem(menu);
NewSubMenu->Caption = TVnode->Text;
BuildMenu(TVnode->getFirstChild(), NewSubMenu);
menu->Add(NewSubMenu);
}
else
{
TMenuItem *NewMenu = new TMenuItem(menu);
NewMenu->Caption = TVnode->Text;
menu->Add(NewMenu);
}
TVnode = TVnode->getNextSibling();
}
}


void __fastcall TForm1::Button3Click(TObject *Sender)
{
TMainMenu *CurrMenu = new TMainMenu(Form1);
BuildMenu(TreeView2->Items->GetFirstNode(), CurrMenu->Items);
Form1->Menu = CurrMenu;
}

только что у меня отработало прекрасно... Только не надо говорить, что это то же самое, хорошо? Это совсем не то же самое smile.gif
ninja
Да действительно не тоже самое, Вы при объявлении переменный сразу присваиваете ей начальное значение, т.е выделяете память для нового объекта, Владимир не могли бы Вы мне объяснить почему именно так работает, а как у меня нет? Спасибо за помощь.
volvo
Цитата
не могли бы Вы мне объяснить почему именно так работает, а как у меня нет?
Могли бы... smile.gif Внимательнее надо быть:
Цитата
	else
{
//NewMenu := TMenuItem.Create(menu);
NewSubMenu = new TMenuItem(menu); // Чего создали? NewSubMenu
NewMenu->Caption = TVnode->Text; // А обращаемся к чему? К NewMenu, а там - мусор...
menu->Add(NewMenu);
}

ninja
мде) что-то я совсем невнимательный ((( спасибо еще раз.
ninja
Возникла еще такая проблема: необходимо сделать так, чтобы при выделении определенной ветки дерева TreeView менялся значок выделенной ветки. Когда добавляю только родительские ветки все работает нормально, а с дочерними проблема, причем если добавить дочерние ветки, а затем выделить родительские которые находятся по уровню ниже, значок меняется совсем в друном месте.


Пробывал сделать таким образом, работает неверно
void __fastcall TForm1::TreeView1Click(TObject *Sender)
{

TreeView1->Items->Item[TreeView1->Selected->Index]->ImageIndex = 2;

}



и так тоже не верно...
void __fastcall TForm1::TreeView1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y)
{
TTreeNode *clickedNode;

clickedNode = TreeView1->GetNodeAt(X,Y);

if (clickedNode != NULL)
{
TreeView1->Items->Item[clickedNode->Index]->ImageIndex = 2;

}

}
volvo
Цитата
таким образом, работает неверно

Цитата
и так тоже не верно...
Глупостями не занимайся... Тебе достаточно только в самом начале назначить для ВСЕХ узлов ImageIndex и SelectedIndex, а дальше - это уже забота TreeView, как при изменении выбранного элемента его правильно отобразить... Смотри:

void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i = 0; i < TreeView1->Items->Count; i++)
{
TreeView1->Items->Item[i]->ImageIndex = 0; // Неактивный Node
TreeView1->Items->Item[i]->SelectedIndex = 1; // Активный Node
}
}

Магия, правда? Теперь запускаешь программу, и все работает (все остальные обработчики, которыми ты пытался колдовать с SelectedItem/ImageIndex надо убрать, они не нужны теперь...)

Кстати, можно каждому узлу вообще назначить свою картинку прямо там же, еще до отображения дерева, можно сказать, что картинку отображать не надо (ImageIndex = -1), все, что угодно...
ninja
В том то и дело, что я хотел сделать чтобы пользователь мог сам выбрать картинку, т.е. кликнув по ветке, затем выбрав картинку, она должна появиться в выбранной ветке. Прошу прощения за неверно поставленный вопрос.
volvo
И все равно - не вижу проблемы: Ну, выбрал элемент. Назначил ему какую-то картинку (откуда - это я сам должен догадаться? Тогда все просто: с диска, да, выбрал и записал в ImageList, тут же последний индекс из ImageList-а присвоил в TreeView1->Selected->SelectedIndex). Дальше что? Хоть засоздавайся потом новыми узлами - те, что ужа были назначены (если правильно создавать новые) менять свои изображения не будут. Не веришь?

Нажмите для просмотра прикрепленного файла

Сначала было добавлено изображение на узел с текстом "12", потом к лежащему выше узлу "11" было добавлено 6 потомков ("adding"), одному из них я опять же сменил картинку, и ПЕРЕД ним опять добавил 3 потомка узлу... Как видишь - ничего не сбилось...
ninja
Владимир очередной раз говорю Вам огромное спасибо, все отлично работает, я как обычно не внимательный, сам себе все усложняю.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.