Добрый день!
Необходимо заполниль дерево с помощью компонента TreeView, имя элемента дерева должно состоять из номеров и имен, т.е. например дерево должно выглядеть следующим образом:
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);
}
}
}
name = IntToStr(selected2)+":";
name = Edit1->Text+":"; // тут опечатка у тебя? может по этому и не правильно?
name += ComboBox1->Items->Strings[ComboBox1->ItemIndex];
Да действительно опечатка, но это всего лишь добаляет имя, тоесть у меня имя берется их 2х компонентов Edit и ComboBox, я просто уже поразному пробывал, текст был закоментирован, я не заметил, если исправить все равно не работает.
присоедини весь проект, а то лень создавать самому
А дочерние можно нумеровать, используя не 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);
}
Вот проект:
TreeView.rar ( 7.07 килобайт )
Кол-во скачиваний: 381
Владимир спасибо Вам огромное все прекрасно работает, как то я проглядел этот свойство у TreeView
Еще такой вопрос: как реализовать создание пунктов меню на основе полученного дерева? т.е Мне необходимо создать, используя компонент MainMenu, пункты меню, учитывая все уровни вложенности полученного дерева, не могу понять как мне это сделать.
получилось пока следующее:
TMenuItem *Menu;
for (i = 0; i < TreeView1->Items->Count; i++)
{
Menu = new TMenuItem(0);
Menu->Caption = "Пункт меню " + IntToStr(i+1);
MainMenu1->Items->Add(Menu);
}
Так лень мне Билдер запускать... Дельфи открытая, поэтому сделаю здесь (переносится на Билдер практически один в один)
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;
Владимир спасибо, на делфи все отлично работает, я в Билдер перенес, но почему-то ничего не создается, вроде все проверил, по нажатию на кнопку никакой реакции....
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;
}
Значит, плохо перевел:
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;
}
Да действительно не тоже самое, Вы при объявлении переменный сразу присваиваете ей начальное значение, т.е выделяете память для нового объекта, Владимир не могли бы Вы мне объяснить почему именно так работает, а как у меня нет? Спасибо за помощь.
else
{
//NewMenu := TMenuItem.Create(menu);
NewSubMenu = new TMenuItem(menu); // Чего создали? NewSubMenu
NewMenu->Caption = TVnode->Text; // А обращаемся к чему? К NewMenu, а там - мусор...
menu->Add(NewMenu);
}
мде) что-то я совсем невнимательный ((( спасибо еще раз.
Возникла еще такая проблема: необходимо сделать так, чтобы при выделении определенной ветки дерева 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;
}
}
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
}
}
В том то и дело, что я хотел сделать чтобы пользователь мог сам выбрать картинку, т.е. кликнув по ветке, затем выбрав картинку, она должна появиться в выбранной ветке. Прошу прощения за неверно поставленный вопрос.
И все равно - не вижу проблемы: Ну, выбрал элемент. Назначил ему какую-то картинку (откуда - это я сам должен догадаться? Тогда все просто: с диска, да, выбрал и записал в ImageList, тут же последний индекс из ImageList-а присвоил в TreeView1->Selected->SelectedIndex). Дальше что? Хоть засоздавайся потом новыми узлами - те, что ужа были назначены (если правильно создавать новые) менять свои изображения не будут. Не веришь?
Сначала было добавлено изображение на узел с текстом "12", потом к лежащему выше узлу "11" было добавлено 6 потомков ("adding"), одному из них я опять же сменил картинку, и ПЕРЕД ним опять добавил 3 потомка узлу... Как видишь - ничего не сбилось...
Владимир очередной раз говорю Вам огромное спасибо, все отлично работает, я как обычно не внимательный, сам себе все усложняю.