http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 
 

Советы по работе с компонентом TTreeView в среде разработки Delphi

 
Автор: Владислав Демьянишин
 
Что и говорить, одним из ярчайших и весьма полезных из плеяды компонентов Delphi является визуальный компонент TTreeView. Он позволяет осуществить построение иерархического дерева из списка и сделать это весьма просто и быстро.
 
Но не каждый начинающий программист догадается, как правильно с ним работать, чтобы скорость выполнения операций была максимально быстрой.
 
Например, в своем 3D-аниматоре для построения иерархической структуры виртуальной сцены я использую компонент TTreeView. И довольно часто сталкиваюсь с ситуациями, когда 3D-сцена содержит тысячи деталей, составляющих список дерева в TreeView. Особенно чувствуется замедление работы программы при загрузке модели из формата OBJ, когда в ней содержатся тысячи деталей.
 
Советы по работе с компонентом TTreeView в среде разработки Delphi
 

Быстрое создание узлов TTreeNode в TTreeView

 
Изучив документацию по компоненту TTreeView, многие программисты составляют примерно следующий код, который успешно добавляет узел.
 
var Node, NewNode : TTreeNode;
begin
Tree.Items.AddChildObject( Node, Model.Name, Model );
NewNode := Tree.Items[Count-1];
NewNode.ImageIndex := …;
NewNode.SelectedIndex := …;
 
Такой код кажется логичным, если опираться лишь на документацию. Но если подобный код использовать в цикле с тысячами итераций, то станет ощутимо заметно замедление работы программы. И для ускорения не поможет даже заключение этого кода в блок Tree.Items.BeginUpdate ... Tree.Items.EndUpdate.
 
Гораздо большей (и, по сути, оптимальной) скорости работы программы можно добиться, немного изменив код:
 
var Node, NewNode : TTreeNode;
begin
NewNode := Tree.Items.AddChildObject( Node, Model.Name, Model );
NewNode.ImageIndex := …;
NewNode.SelectedIndex := …;
 
Поскольку метод Tree.Items.AddChildObject в качестве результата возвращает созданный узел, то получать его через жутко медленно работающую комбинацию Tree.Items[Count-1] (для получения последнего узла) нет необходимости.
 

Быстрый поиск узла TTreeNode

 
Предположим, что у нас возникла необходимость перебрать весь список узлов, чтобы найти некий узел по конкретному критерию. Допустим, будем искать по его тексту. Тогда совершенно логично и в соответствии с документацией напрашивается следующий код для решения нашей задачи:
 
var j : integer;
      Node : TTreeNode;
begin
Result:=nil;
j:=0;
while j do begin
         Node := Tree.Items[j];
         if Node.Text = … then begin
            Result := Node;
            Exit;
            end;
        inc(j);
        end; // while
 
Такой код будет работать успешно, но в случае с наличием в дереве огромного количества узлов поиск затянется многократно.
 
Разгадка кроется в исходном коде компонента, который не мешало бы просмотреть, примерно, по такому пути: c:/Program Files/Borland/Delphi/SOURCE/VCL/comctrls.pas
 
Дело в том, что комбинация Tree.Items[j] всякий раз осуществляет прогон списка узлов с самого начала. В итоге, с каждой итерацией нашего цикла очередная итерация выполняется все дольше и дольше, то есть тем дольше, чем ближе индекс узла к концу списка.
 
Внимательное изучение исходного кода компонента учит нас делать правильно. А именно – мы самостоятельно можем и должны обратиться к первому узлу, а далее просто перебирать следующие, не забегая в начало.
 
Так, в случае с 10 000 узлами в дереве поиск при помощи предыдущего кода затянулся бы на несколько минут. А вот следующий код сделает все мгновенно:
 
var j : integer;
      Node : TTreeNode;
begin
Result:=nil;
j:=0;
Node := Tree.Items.GetFirstNode;
while (Node <> nil) do begin
         if Node.Text = … then begin
            Result := Node;
            Exit;
            end;
         Node := Node.GetNext;
         end; // while
 

Отключаем подсказки в TTreeView

 
По умолчанию, в компоненте активна такая опция, при которой при наведении курсора мышки на узел выскакивает подсказка (Hint) и остается видна довольно долго.
 
Отключаем подсказки в TTreeView
 
При работе с деревом это может ужасно мешать и раздражать. Советов по отключению подсказки в TTreeView в Интернете хватает, но самый действенный и универсальный для всех версий Delphi, на мой взгляд, следующий. Особенно, если возникает необходимость создать свой потомок класса TTreeView:
 
Всего лишь надо перекрыть обработчик для уведомительного сообщения при описании нашего нового класса компонента:
 
type
        TMyTreeView = class (TCustomTreeView)
        private
        { Private declarations }
         procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
        protected
        …
 
implementation
 
procedure TMyTreeView.WMNotify( var Message: TWMNotify );
begin
// следующую строку не выполняем, чтобы выключить автоподсказку при наведении курсора на ветку дерева
//inherited;
end;
 
Вот, собственно, и все.
Желаю успешного программирования!
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > Советы по работе с компонентом TTreeView в среде разработки Delphi
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы