Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.09.19;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.03 c
6-1089732673
banderas
2004-07-13 19:31
2004.09.19
idTCPServer & idTCPClient Есть ли альтернатива readln ???


1-1094532933
BillyJeans
2004-09-07 08:55
2004.09.19
override private метода...


14-1093589496
saNat
2004-08-27 10:51
2004.09.19
Electronics Workbench


1-1094263572
O?O
2004-09-04 06:06
2004.09.19
Адрес E.Mail


14-1093664170
Думкин
2004-08-28 07:36
2004.09.19
С днем рождения! 28 августа





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский