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

Вниз

Работа с TreeView, как "нарисовать" дерево   Найти похожие ветки 

 
STK ©   (2006-04-10 21:34) [0]

Проблема такая, что я думаю многие кто сталкивался.

Есть ini файлы в которых прописаны некоторые данные. И имеется связьмежду ними. Лучше наверно показать.
Строки из ini файла:

[первый]
количество связей = 2
связь №1 = второй
связь №2 = четвёртый
связь выше = нуль
[второй]
количество связей = 1
связь №1 = третий
связь выше = первый
[третий]
количество связей = 0
связь выше = второй
[четвёртый]
количество связей = 2
связь №1 = пятый
связь №2 = шестой
связь выше = первый

Т.е. у [номер] есть запись сколько у него связей, и номера с тем с кем он связан. У [номера] есть только одна связь сверху, и может быть несколько с тем кто ниже.

Вот эти связи необходимо нарисовать в TreeView.

Кто может помогите пожалуйста. Заранее всем спасибо.


 
STK ©   (2006-04-10 21:40) [1]

Если что-то непонятно, я распишу.


 
Мефисто   (2006-04-10 22:16) [2]

\Delphi\Demos\CustomDraw


 
STK ©   (2006-04-10 22:55) [3]


> Мефисто   (10.04.06 22:16) [2]
> \Delphi\Demos\CustomDraw

Нет это не-то мне надо формировать дерево, а там красят и всё такое. Так и я могу. Мне нужен алгоритм. Чтоб он с самого первого работал и до последнего. Иерархию строил. Чтоб каждая запись одна под другой. Наверняка такая тема у кого-нить всплывала. А алгоритм который я придумал боюсь  заставит зависнуть ПК при количестве связей более 1000, а у меня их с 5000 если небольше.


 
Мефисто   (2006-04-10 23:09) [4]

// не будет заморачиваться с отрисовкой на время создания веток
 TreeView1.Items.BeginUpdate;

 TreeView1.Items.Add - подробнее по F1
 строй ветки как хочешь...
 ...

 TreeView1.Items.EndUpdate;


 
STK ©   (2006-04-10 23:16) [5]


> Мефисто   (10.04.06 23:09) [4]
> // не будет заморачиваться с отрисовкой на время создания
> веток
>  TreeView1.Items.BeginUpdate;
>
>  TreeView1.Items.Add - подробнее по F1
>  строй ветки как хочешь...
>  ...
>
>  TreeView1.Items.EndUpdate;

Ты не понял. Мне надо алгоритм, чтоб он их из файлов брал и вставлял в TreeView. Т.е. сначала самый первый, затем все вторые (ну как параметр Level), затем третьи, и т.д. но так чтоб каждый под своим был. Это дерево может иметь "не постоянный рисунок" где-то закончиться на 5 уровне, а где-то на 100 уровне.   МНЕ НУЖЕН Алгоритм. Вот ивсё. А добавлять записи-стоки-"листочки дерева" я умею.

Может чего придумаеш. Но мой алгоритм очень плох.


 
Мефисто   (2006-04-10 23:20) [6]

Тогда Т.З. шире раскрой. А то по первому посту не очень възжаю чего надо. Ини файл сразу в сторону т.к. для алгоритма он не важен. Типа, чего за записиси и по каким признакам их нужно сгруппировать...


 
STK ©   (2006-04-10 23:34) [7]

Одним словом покажу суть: представь
Ты знаеш что такое сетевой маркетинг? Как там иерархия строится? Так вот это полный прототип. Есть "человек" который знает кто у него главный-это с одной стороны, и есть его дистребютеры(чёрт знает как писать). Он знает только их имена и их количество.
Так вот дерево надо строить с первого. потом прикрепитьк нему вторых. затем каждому второму надо прикрепить их третьих. чтоб там не получилось что он принадлежал одному а оказался в связи с другим.

Ну незнай как там Тех Задан получилось, но с сетевым маркетингом очень похож. Если не понятно могу вообще на пальцах объяснить, но это тяжело.


 
Мефисто   (2006-04-10 23:46) [8]

Если такого рода связи,

http://slil.ru/22673768

то вчем проблема? Ветки ты говоишь строить умеешь. А судя по ини файлу, ты ведь инфу как-то по признакам групперуешь.  Что мешает сделать тоже самое но с ветками? До меня пока не доходит :)


 
STK ©   (2006-04-10 23:56) [9]

Вай, Вай, Вай.

Всё это понятно. Может я чего не знаю о TreeView? Из-за этого у меня не чё и не прёт.

Но с этим всё понятно(с рисунком). Мне надо чтоб после того как я добавил последнего участника одного уровня. Начать добавлять участника следующего уровня. Но как запомнить с кого начать, и кем дальше продолжить. если на одном уровне может быть около 1000 записей. Сам посмотри на рисунке на 3 уровне сколько. а на 30 уровне-очень много.

А cделать
TreeView.items.add(); я могу . - но как тут вставить именно ту ветвь в которую надо вставить я не знаю. Нужно чтоб оптимально и быстро.


 
Мефисто   (2006-04-11 00:10) [10]

Посмотри по справке внимательно, что возвращает TreeView.items.add.
Правильно, ссылку на созданную вновь ветку дерева.
Про рекурсивный вызов процедур/функций слышал? Это в твоем случае может очень почочь. И глянь еще раз справку, может поможет. А с кодом может завтра если чего накидаю и то ближе к полуночи. Но я думаю ты и сам справишся :)


 
PZ   (2006-04-11 09:00) [11]

Посмотрите, может поможет:
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=488


 
STK ©   (2006-04-11 10:48) [12]


> Мефисто   (11.04.06 00:10) [10]

Про рекурсию слыхал. Мой алгоритм просто в цикле сделан, может из-за этого. Но не думаю.

Ещё это может помешать закрытию файлов ini (помоему может). Но попробую, посмотрю что получится.

> PZ   (11.04.06 09:00) [11]
> Посмотрите, может поможет:
> http://www.delphikingdom.com/asp/viewitem.asp?catalogID=488

Посмотрю, вроде оно, ведь они тоже строят исходя из связей, Но ...
Спасибо посмотрю.


 
STK ©   (2006-04-12 00:02) [13]

Нечего не понятно, если честно. Но явного построения нет, этонаверняка.
Может кто чего другого предложит, очень нужно.


 
ЮЮ ©   (2006-04-12 11:47) [14]

Держи, я сегодня добрый.
Однако здесь нет проверки на вложенные зацикливания,типа

[первый]
связь выше = второй
[второй]
связь выше = первый

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ComCtrls;

type
 TForm1 = class(TForm)
   TreeView1: TTreeView;
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

uses IniFiles;

{$R *.dfm}

procedure FillTreeFromIni(TreeView: TTreeView; ini: TMemIniFile);
var
 sl: TStringList;
 i: integer;
 parent: string;
 parentIdx: integer;
 children, root: TList;

 procedure FillNode(Root: TTreeNode; Children: TList);
 var
   i, idx: integer;
   node: TTreeNode;
   list: TList;
 begin
   for i := 0 to Children.Count - 1 do begin
     idx := Integer(Children[i]);
     node := TreeView.Items.AddChild(Root, sl[idx]);
     list := TList(sl.Objects[idx]);
     if list <> nil then begin
       FillNode(node, list)
     end;
   end;
 end;

begin
 sl := TStringList.Create;
 root := TList.Create;
 try
   ini.ReadSections(sl);
   for i := 0 to sl.Count - 1 do sl.Objects[i] := nil;
     //sl.Object заполнено "строками" секции, а мы намерены
     //испльзовать для списка детей

   // создаем виртуальное дерево
   for i := 0 to sl.Count - 1 do begin
     parent := ini.ReadString(sl[i], "связь выше", "");
     if parent = "нуль" then
       root.Add(TObject(i))
     else begin
       parentIdx := sl.IndexOf(parent);
       if parentIdx < 0 then
         //связь выше имеет недопустимое значение
       else if parentIdx = i then
         //ссылка на самого себя
       else begin
         if sl.Objects[parentIdx] = nil then
            sl.Objects[parentIdx] := TList.Create;
         children := TList(sl.Objects[parentIdx]);
         children.Add(TObject(i))
       end;
     end;
   end;

   // заполняем TreeView
   if not Assigned(TreeView) then Exit;

   TreeView.Items.BeginUpdate;
   try
     TreeView.Items.Clear;
     TreeView.Items.Add(nil, "нуль");
     FillNode(TreeView.Items[0], root);
   finally
     TreeView.Items.EndUpdate;
   end;
 finally
   for i := 0 to sl.Count - 1 do
     sl.Objects[i].Free;
    sl.Free;
    root.Free;
 end;
end;

procedure FillTreeFromFile(TreeView: TTreeView; FileName: TFileName);
// ТMenIniFile и TStringList не имеют ограничений по размеру,
// в отличии от TIniFile
var
 sl: TStringList;
 ini: TMemIniFile;
begin
 sl := TStringList.Create;
 ini := TMemIniFile.Create("tree.ini");
 try
   sl.LoadFromFile(FileName);
   ini.GetStrings(sl);
   FillTreeFromIni(TreeView, ini);
 finally
   sl.Free;
   ini.Free;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FillTreeFromFile(TreeView1, ExtractFilePath(ParamStr(0)) + "tree.ini");
end;

end.


 
STK ©   (2006-04-12 22:16) [15]


> ЮЮ ©   (12.04.06 11:47) [14]
> Держи, я сегодня добрый.
> Однако здесь нет проверки на вложенные зацикливания,типа
>
>
> [первый]
> связь выше = второй
> [второй]
> связь выше = первый

Спасибо большое. Но у меня и нет подобного.

Как я по первому взгляду пойму - это дерево строится сразу и полностью?
или как?
И если можно чуть больше коментариев, правда это уже наглость, но я чувствую что ты и сегодня добрый будеш, но это на твоё усмотрение.

Ещё раз спасибо.


 
STK ©   (2006-04-12 22:56) [16]


> ЮЮ ©   (12.04.06 11:47) [14]
> Держи, я сегодня добрый.
> Однако здесь нет проверки на вложенные зацикливания,типа
>

Всё работает как часы. Это очень круто. Спасибо что ты мне помог. Я уже протестировал код. Работает. Поповоду коментариев - ненадо. Походу пошагового я разобрался более или менее. Правда вот есть такая тема, что если файлов более чем один. Буду конечно сам разбираться, но...

И если можно: что это затип TMemIniFile - некогда не слыхал и не видал. Какой унит в усес подключать?
Что-то Архангельский(моя настольная книга)про это умалчивает. Только не надо про книги. Я на них уже ~1500р. потратил и нового покупать не хочу, ПОКА. Если только Пачеко и Тейксера.

И чё-то у меня пробел не фурычит, так-что не обессутьте за отсутствие пробелов.


 
STK ©   (2006-04-12 23:15) [17]

Что-то в инете копаю, а инфы толком нет.

Ещё что-то дельфийская помощь умерла: показывает что не может найти d7.hlp, при этом показывает  весь путь без слешей "\". Хрень какая-то. Наверно придётся ручками исправлять.

Может кто подскажет ли ссылочку покажет?

Заранее же спасибо.


 
STK ©   (2006-04-12 23:21) [18]

Блин куда я смотрю: типто называется ТMenIniFile а я ищу ТMemIniFile. Всё пора спать. В Уфе уже 1:21. всем спокойного времени суток.


 
STK ©   (2006-04-12 23:25) [19]


> procedure FillTreeFromFile(TreeView: TTreeView; FileName:
>  TFileName);
> // ТMenIniFile и TStringList не имеют ограничений по размеру,
>
> // в отличии от TIniFile
> var

Я отсюда взял ТMenIniFileа оказывается точно ТMemIniFile. Это доказывает: людям свойственно ошибаться.

Всё проблема решена. Но мне надо использовать несколько файлов ini - а этозначитнадодумать дальше.


 
STK ©   (2006-04-20 22:05) [20]


>  sl := TStringList.Create;
>   ini.ReadSections(sl);


А можно ли здесь зделать так:

ini - ini файл

sl := TStringList.Create;
for i:=0 to N do
iniN.ReadSections(sl);


т.е. добавлять к sl ещё строки из других инишников.

Или это делается другимиметодами?



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

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

Наверх




Память: 0.53 MB
Время: 0.047 c
1-1143727351
MegaVolt
2006-03-30 18:02
2006.05.07
Range Check Error


1-1143728730
kyn66
2006-03-30 18:25
2006.05.07
Добавить информацию в EXE-шник


15-1144835643
Гость101
2006-04-12 13:54
2006.05.07
Родительный падеж


10-1118746276
Непоседа
2005-06-14 14:51
2006.05.07
Подскажите, что я забыл задекларировать


2-1145512235
wowik_cn
2006-04-20 09:50
2006.05.07
TabbedNotebook - активная вкладка