Форум: "Основная";
Текущий архив: 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.034 c