![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Tree Walker: Create [D6, Win2k]
Satirus © (2002-04-19 17:14:00)Вопрос к умудрённым опытом в использовании компонента TTreeView.
Предложите оригинальный код для перебора веток дерева снаружи внутрь. То есть, как пройтись сначала по сиблингам корня, потом по их детям, потом по сиблингам детей и т. д., до последнего колена в глубину
Набережных С. (2002-04-20 20:43:00) [1]Письмо получил. Дело в том, что строка
Nodes[level,ChildCount]:=TreeView.Items[NodeCount];
стоит внутри блока with и у TTreeNode есть свойство TreeView: TCustomTreeView, а у TCustomTreeView свойство Items не опубликовано. Измени имя параметра TreeView и все будет нормально.
Satirus (2002-04-20 20:04:00) [2]>>Набережных С. Я его отправил Вам на мыло
Набережных С. (2002-04-20 19:29:00) [3]
> Satirus © (20.04.02 19:05)
У меня на D5 не выдает. Возможно, в D6 изменили TTreeView, но тут я помочь не смогу. А ты никаких изменений не вносил? Покажи на всякий случай свой код.
Satirus (2002-04-20 19:05:00) [4]>>Набережных С. Ваш пример выдает ошибку Undeclared identifier "Items"
Набережных С. (2002-04-19 22:43:00) [5]Пример с массивом:
type
TArr = array of array of TTreeNode;
procedure Parse(TV: TTreeView; var A: TArr);
var
n,m,k:integer;
begin
m:=0; n:=0;
while n < TV.Items.Count do
with TV.Items[n] do
begin
if Level >= m then
begin
m:=Level + 1;
SetLength(A,m);
end;
k:=Length(A[Level]);
SetLength(A[Level],k+1);
A[level,k]:=TV.Items[n];
Inc(n);
end;
end;
Пример вызова:
var
Arr:TArr;
Parse(TreeView1,Arr);
for n:= 0 to Pred(Length(Arr)) do
begin
for m:=0 to Pred(Length(Arr[n]))do
Memo1.Lines.Add(StringOfChar(" ",Arr[n,m].Level*4)+Arr[n,m].Text);
end;
vuk (2002-04-19 21:38:00) [6]Ну и какие проблемы? Переписать создание узлов - и все дела. А как атрибуты вытягивать - я Вам уже писал.
Satirus (2002-04-19 21:32:00) [7]>>vuk Этот пример я разбирал первым делом. Но там один недостаток: ветки названы по типу, а не по имени элемента, к тому же сложно вытянуть атрибуты каждой ветки...
vuk (2002-04-19 21:10:00) [8]Дерево-то проще всего вытягивать рекурсивно, а не по уровням. Все достаточно прозрачно получается. В составе XDOM даже пример имеется как это сделать.
имя файла:
\example03\example03main.pas
Метод:
procedure TMainpage.UpdateTreeView(const doc: TdomDocument);
Satirus (2002-04-19 21:01:00) [9]>>vuk Возвращаясь к вопросу использования библиотеки XDOM, хочу спросить Вас, не использовали ли Вы её встроенный TDOMTreeWalker, подобие которого я и пытаюсь создать, но в облегченном варианте. Целевым объектом триволкера является всё тот же XML-file, но вот незадача, не могу его побороть! Может у Вас найдется пару простеньких примерчиков по вытягиванию древа из XML-file?
Буду очень признателен.
MBo (2002-04-19 19:22:00) [10]>StringList - это не выход :))
это демонстрация подхода, но вполне рабочий вариант
>Это слишком просто и медленно :))
все зависит от диаметры иглы - количества items
Satirus (2002-04-19 18:56:00) [11]vuk-> Ну да. Мне надо пройтись по уровням
vuk (2002-04-19 18:32:00) [12]Рекурсия не пойдет. Я немного не верно понял задачу. Нормальным решением рекурсия будет только тогда, когда нужен проход в таком порядке: сначала корень, потом его первый дочерний узел, и т.д. в глубь, т.е. каждая ветка проходится до конца перед тем как будет пройдена другая ветка. У Вас же условие другое - перебор должен идти по уровням, а не по веткам.
Дмитрий Баранов (2002-04-19 18:30:00) [13]>> MBo © (19.04.02 18:25)
Тоже на коленках :) ?
Меня, например удивляет, почему в Delphi встроеных хэшей и мапов нет :)) StringList - это не выход :)) Это слишком просто и медленно :))
MBo (2002-04-19 18:25:00) [14]procedure TForm1.Button1Click(Sender: TObject);
var sl,sl2:TStringlist;
i,j,k:integer;
begin
sl:=tstringlist.create;
sl2:=tstringlist.create;
for i:=0 to tv1.Items.count-1 do begin
j:=tv1.items[i].level-sl.count+1;
if j>0 then
for k:=1 to j do sl.add("");
sl[tv1.items[i].Level]:=sl[tv1.items[i].Level]+inttostr(i)+" ";
end;
for i:=0 to sl.count-1 do begin
memo1.lines.add("Level "+inttostr(i));
sl2.commatext:=sl[i];
for j:=0 to sl2.count-1 do
memo1.lines.add(tv1.items[strtoint(sl2[j])].text);
end;
sl.free;
sl2.free;
end;
Дмитрий Баранов (2002-04-19 18:24:00) [15]На коленках - рекурсия.
procedure Recurse(const Node: TTreeNode);
var i: integer;
begin
ShowMessage(Node.Text);
if not Node.HasChildren then exit
else
begin
for i:=0 to Node.Count-1 do
begin
Recurse(Node.Item[i]);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var Node: TTreeNode;
begin
Node:=TreeView1.Items[0];
Recurse(Node);
end;
Satirus (2002-04-19 18:17:00) [16]vuk-> Меня устраивает рекурсия, но я не знаю, с какой стороны к ней подойти. Можно примерный кусочек кода?
Заранее благодарен
vuk (2002-04-19 18:12:00) [17]Понял свою лажу. Извиняюсь.
Дмитрий Баранов (2002-04-19 18:10:00) [18]Вот с удовольствием бы, только времени нет. Динамический массив как он реализован в Delphi я бы применять не стал, а взял бы аналог С++ map. В Delphi придется извращаться -
Type TArrNode = array of TTreeNode;
Type TTree = array of TArrNode;
(с array of array шибко нечитаемый код получается),
а затем везде впихивать SetLength.
Если это не очень срочно, то могу на выходных подумать.
Satirus (2002-04-19 17:58:00) [19]Дмитрий Баранов-> можно по подробней? Идея динамического массива у меня возникла сразу... Развейте её, пожалуйста, в виде кода
vuk (2002-04-19 17:55:00) [20]А чем рекурсия не устраивает?