Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.19;
Скачать: CL | DM;

Вниз

Создание меню из дерева   Найти похожие ветки 

 
Mitrofan   (2004-08-30 10:29) [0]

Господа, нужен помощь в виде програмного кода.
 Имеем дерево в виде таблицы

Id Parent_Id Name

0  Null      File
1  Null      Edit
2  Null      Help
3  0         New
4  0         Open
5  0         Save
6  2         About

И т.д.

Как по этой табличке построить главное меню программы ?


 
Ega23 ©   (2004-08-30 10:33) [1]

TMainMenu.Items.add ?


 
Mitrofan   (2004-08-30 10:36) [2]

Нужен программный код видимо с рекурсией.
А вот как именно организовать эту рекурсию не могу сообразить.


 
Erik1   (2004-08-30 10:38) [3]

Тебе наверное нужно обойти дерево? И то этому дереву построить меню. Можеш сам придумать рекурсивный алгоритм обхода дерева, а можеш в инете посикать.


 
begin...end ©   (2004-08-30 10:51) [4]

Может быть, что-то вроде этого...

1. Читаем строку таблицы.
2. Если Parent_Id = NULL, то
   {
     NewMenuItem := TMenuItem.Create(MainMenu);
     MainMenu.Items.Add(...)
   }
   иначе
   {
     MenuItem := // вот тут надо как-то найти существующий Item с Parent_Id
     MenuItem.Items.Add(...)
   }


 
Mitrofan   (2004-08-30 10:56) [5]

Вот в этот то и вопрос как его найти ???


 
begin...end ©   (2004-08-30 11:02) [6]

> Mitrofan   (30.08.04 10:56) [5]

Например, можно при создании NewMenuItem записывать его Id в TMenuItem.Tag.
А потом, при поиске, пробежаться по Items и найти Item с нужным Tag.


 
KADAN ©   (2004-08-30 11:06) [7]

в Tag хранить Id или создать массив связок
array[i,0]:=Id;
array[i,1]:=integer(MenuItem);


 
Ega23 ©   (2004-08-30 11:11) [8]

TMainMenu.FindItem?


 
Erik1   (2004-08-30 11:21) [9]

Как сложно воспользоватся поисковиком и набрать "рекурсивный алгоритм обхода дерева".
 Вопрос к отвечающим, ну зачем человеку ерунду советовать если сами незнаете?


 
Mitrofan   (2004-08-30 11:27) [10]

Просто может кто нибудь уже сталкивался с подобной проблемой ?
Меню хранится в базе и его надо создать при запуске приложения.


 
begin...end ©   (2004-08-30 11:29) [11]

> [9] Erik1   (30.08.04 11:21)

> Вопрос к отвечающим, ну зачем человеку ерунду советовать если сами незнаете?

Встречный вопрос: чем Вас ПРИНЦИПИАЛЬНО не устроило [4]?


 
YurikGL ©   (2004-08-30 11:38) [12]

Делал с TTreeNode алгоритм рекурсии примерно такой.

Рекурсия (входной элемента)
В датасет1 выбираем всех детей входного элемента
Создаем динамический список элементов
Если их количество=0 то выход
Иначе
 Для всех элементов датасет1 начало
   добавить в дерево используя в качестве родителя Входной элемент.
   добавить в динамический список
                             конец
Для всего динамического списка применть рекурсию
Удалить динамический список
Выход


 
Erik1   (2004-08-30 11:46) [13]

To begin...end
Вопрос был как построить мену по дереву. А твой ответ подрузамевает выкинуть часть алгоритма обхода. Общий метод потом ненаписать если пойдеш по указаному тобой пути. Если бы ты просто написал
NewMenuItem := TMenuItem.Create(MainMenu);
MainMenu.Items.Add(...)
то я бы неимел ничего против. А так включил в общею компанию :)


 
DesWind ©   (2004-08-30 11:54) [14]

Таблицу можно скэшировать.
TCacheItem=class(TObject)
ID: integer;
ParentID: integer;
Value: string;
end;

TCache=class(TObjectList);

procedure AddChild(ID:integer);
var
c: integer;

begin
for c:=0 to cacheList.Count-1 do
if CacheList[c].ParentID=ID then
 begin
  ...// добавление дочернего элемента в меню
 if IsParent(CacheList[c].ID) then AddChild(CacheList[c].ID);
 end;

end;

for c:=0 to cacheList.Count-1 do
if CacheList[c].ParentID=0 then
 begin
  ...// добавление корневого элемента в меню
 if IsParent(CacheList[c].ID) then AddChild(CacheList[c].ID);
 end;

Это у меня для TreeView так что может придется кой че подправить


 
begin...end ©   (2004-08-30 12:00) [15]

>  [13] Erik1   (30.08.04 11:46)

> Вопрос был как построить мену по дереву

Вопрос был: Как по этой табличке построить главное меню программы ?

Ещё раз: методом [4] этого принципиально нельзя сделать?


 
Erik1   (2004-08-30 16:51) [16]

To begin...end
Я флеймом незанимаюсь. :)


 
begin...end ©   (2004-08-30 17:31) [17]


> [16] Erik1   (30.08.04 16:51)

Неужели? А что же тогда представляет из себя Ваш пост [9] ?

Вот Вам код:

var
 I, J: Integer;
 NewMenuItem: TMenuItem;
 FArray: array [0..6, 1..3] of String;
begin

 // Имитация чтения файла

 FArray[0, 1] := "0";
 FArray[1, 1] := "1";
 FArray[2, 1] := "2";
 FArray[3, 1] := "3";
 FArray[4, 1] := "4";
 FArray[5, 1] := "5";
 FArray[6, 1] := "6";
 FArray[0, 2] := "Null";
 FArray[1, 2] := "Null";
 FArray[2, 2] := "Null";
 FArray[3, 2] := "0";
 FArray[4, 2] := "0";
 FArray[5, 2] := "0";
 FArray[6, 2] := "2";
 FArray[0, 3] := "File";
 FArray[1, 3] := "Edit";
 FArray[2, 3] := "Help";
 FArray[3, 3] := "New";
 FArray[4, 3] := "Open";
 FArray[5, 3] := "Save";
 FArray[6, 3] := "About";

 // Заполнение меню

 for I := 0 to 6 do
   if FArray[I, 2] = "Null" then
   begin
     NewMenuItem := TMenuItem.Create(MainMenu);
     NewMenuItem.Tag := I;
     NewMenuItem.Caption := FArray[I, 3];
     MainMenu.Items.Add(NewMenuItem);
   end
   else
   begin
     for J := 0 to MainMenu.Items.Count - 1 do
       if MainMenu.Items[J].Tag = StrToInt(FArray[I, 2]) then
       begin
         NewMenuItem := TMenuItem.Create(MainMenu);
         NewMenuItem.Caption := FArray[I, 3];
         MainMenu.Items[J].Add(NewMenuItem);
       end;
   end;

end;


Коряво, некрасиво, нерационально? НЕ СПОРЮ.
Но - это корректно обрабатывает таблицу, указанную в [0].
А Вы в [9], насколько я понял, намекали на то, что это неправильно.

Но давайте не будем больше спорить.
Возможно, мы просто по-разному поняли задание.
Без обид.

:-)

---
Sorry, I"m drunk now


 
Mitrofan   (2004-08-31 10:18) [18]

> begin...end
Данный код не пропустит следующую струтктуру
FArray[7, 1] := "7";
FArray[7, 2] := "3";
FArray[7, 3] := "New 1";

Т.е. если дерево имеет более сложную иерерхию чем представлено в [0]


 
AlexSV   (2004-08-31 11:59) [19]

> Mitrofan
есть два варианта построения меню:
(в примерах MenuTable - таблица из вопроса)
1. прямой проход по таблице.
Поскольку у MainMenu нет сквозного списка его Item"ов,
то создаем массив array of TMenuItem
пример:
procedure TForm1.FormShow(Sender: TObject);
var
 ItemList: array of TMenuItem;
begin
 with MenuTable do begin
   Open;
   SetLength(ItemList, RecordCount);
   try
     First;
     while not Eof do begin
       ItemList[FieldByName("id").AsInteger] := TMenuItem.Create(MMenu);
       ItemList[FieldByName("id").AsInteger].Caption := FieldByName("Name").AsString;
       if FieldByName("parent_id").IsNull then begin
         MMenu.Items.Add(ItemList[FieldByName("id").AsInteger]);
       end else
         ItemList[FieldByName("parent_id").AsInteger].Add(ItemList[FieldByName("id").AsInteger]);
       Next;
     end;
   finally
     SetLength(ItemList, 0);
     Close;
   end;
 end;
end;

2. Рекурсивный обход с фильтрацией набора данных.
пример:
procedure TForm1.CreateSubMenu(AMenu: TMenu; AMenuItem: TMenuItem; ADataSet: TDataSet);
var
 ParentItem, NewItem: TMenuItem;
 ItemID: integer;
begin
 with ADataSet do begin
   if AMenuItem = nil then begin
     Filter := "Parent_id = -1";
     ParentItem := AMenu.Items;
   end else begin
     Filter := "Parent_id = " + IntToStr(AMenuItem.Tag);
     ParentItem := AMenuItem;
   end;
   Filtered := True;
   First;
   while not Eof do begin
     NewItem := TMenuItem.Create(MMenu);
     NewItem.Caption := FieldByName("Name").AsString;
     NewItem.Tag := FieldByName("id").AsInteger;
     ParentItem.Add(NewItem);
     Next;
   end;
   Filtered := False;
   if (ParentItem.Count > 0) then
     for ItemID := 0 to ParentItem.Count - 1 do begin
       CreateSubMenu(AMenu, ParentItem.Items[ItemID], ADataSet);
       if (ParentItem.Items[ItemID].Count = 0) then
         ParentItem.Items[ItemID].OnClick := ItemClick;
     end;
 end;
end;

procedure TForm1.ItemClick(Sender: TObject);
begin
 ShowMessage(TMenuItem(Sender).Caption);
end;

запуск процедуры создания меню:
procedure TForm1.FormShow(Sender: TObject);
begin
 MenuTable.Open;
 try
   CreateSubMenu(MMenu, nil, MenuTable);
 finally
   MenuTable.Close;
 end;
end;


 
AlexSV   (2004-08-31 12:04) [20]

Дополнение:
во втором примере
Filter := "Parent_id = -1";
т.е. вместо
Null в Parent_id надо поставить -1
При фильтрации Null воспринимается как 0



Страницы: 1 вся ветка

Текущий архив: 2004.09.19;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.057 c
1-1094471745
VKSam
2004-09-06 15:55
2004.09.19
Бинарные файлы


10-1038487107
Павел
2002-11-28 15:38
2004.09.19
просьба помочь


14-1093587725
peypivo
2004-08-27 10:22
2004.09.19
американцы и луна


14-1093594511
gn
2004-08-27 12:15
2004.09.19
Мат как способ само выражения или опросто недостаточно словарного


14-1093586057
MBo
2004-08-27 09:54
2004.09.19
Пятничная разминка. Задачки для ума и сердца ;)