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