Несколько небольших статей по компоненту TreeView
Несколько небольших статей по компоненту TreeView
Несколько небольших статей по компоненту TreeView Получение доступа к узлам treeview Автор: peter kane Небольшие хитрости для работы с узлами treeview: Если вы хотите производить поиск по дереву, может быть для того, чтобы найти узел, соответствующий определенному критерию, то НЕ ДЕЛАЙТЕ ЭТО ТАКИМ ОБРАЗОМ: for i := 0 to pred(mytreeview.items.count) do begin if mytreeview.items[i].text = 'Банзай' then break; end; ...если вам не дорого время обработки массива узлов. Значительно быстрее будет так: noddy := mytreeview.items[0]; searching := true; while (searching) and (noddy <> nil) do begin if noddy.text = searchtarget then begin searching := false; mytreeview.selected := noddy; mytreeview.setfocus; end else begin noddy := noddy.getnext end; end; В моей системе приведенный выше код показал скорость 33 милисекунды при работе с деревом, имеющим 171 узел. Первый поиск потребовал 2.15 секунд. Оказывается, процесс индексирования очень медленный. Я подозреваю, что при каждой индексации свойства items, вы осуществляете линейный поиск, но это нигде не засвидетельствовано, поэтому я могу ошибаться. Вам действительно не нужно просматривать все дерево, чтобы найти что вам нужно - получить таким образом доступ к mytreeview.items[170] займет много больше времени, чем получения доступа к mytreeview.items[1]. Как правило, для отслеживания позиции в дереве treeview, нужно использовать временную переменную ttreenode, а не использовать целочисленные индексы. Возможно, свойство itemid как раз и необходимо для такого применения, но, к сожалению, я никак не могу понять абзац в электронной документации, касающийся данного свойства: "Свойство itemid является дескриптором ttreenode типа htreeitem и однозначно идентифицирует каждый элемент дерева. Используйте это свойство, если вам необходимо получить доступ к элементам дерева из внешнего по отношению к treeview элемента управления." "Я разговаривал с деревьями...вот почему они ушли от меня...." (spike milligan).. *************************************************************************** Получить строковый путь в ttreeview function srnodetree(ptreenode: ttreenode; var sruta: string): string; begin sruta := ptreenode.text + ' > ' + sruta; if ptreenode.level = 0 then result := sruta else result := srnodetree(ptreenode.parent, sruta); end; {*--------------------------------------------- click an item ---------------------------------------------*} procedure tform1.treeview1click(sender: tobject); var spath: string; begin label1.caption := srnodetree(treeview1.selected, spath); end; ***************************************************************************** Поточность treeview На пустой форме у меня располагается ttreeview. Затем я сохраняю это в файле, используя writecomponent. Это работает как положено; я могу из dos c помощью команды "type" посмотреть двоичный файл и увидеть его содержимое, типа строк ttreeview и имя объекта. По крайней мере файл записывается и создается впечатление его "наполненности". Затем я освобождаю компонент ttreeview, открываю поток, делаю readcomponent и, затем, insertcontrol. И получаю исключение "treeview1 has no parent window" (treeview1 не имеет родительского окна). Это происходит из-за того, что при установке определенных свойств treeview требуется дескриптор окна элемента управления, а для этого необходимо иметь родителя. Решение заключается в создании пустого treeview и передаче его в качестве параметра readcomponent - вы наверняка меня спросите, почему readcomponent необходим параметр, правильно? Смотрите дальше. Попробуйте этот код: procedure tform1.button1click(sender: tobject); var treeview: ttreeview ; begin with tfilestream.create( 'junk.str', fmcreate ) do try writecomponent( treeview1 ) ; treeview1.name := 'treeview' ; position := 0 ; treeview := ttreeview.create( self ) ; treeview.visible := false ; treeview.parent := self ; readcomponent( treeview ) ; treeview.top := treeview1.top + treeview1.height + 10 ; treeview.visible := true ; finally free ; end ; end; Два небольших замечания: 1. Убедитесь в отсутствии конфликта имен. Данный код делает форму владельцем второго treeview и при ее освобождении разрушает компонент. Я просто переименовываю существующий treeview перед загрузкой 'клона'. 2. Я установил свойство visible в false перед установкой свойства parent, этим я предотвратил показ только что созданного treeview до момента загрузки его из потока. ********************************************************************************* Прокрутка treeview, чтобы держать выделение посередине procedure tmyform.treechange(sender: tobject; node: ttreenode); var i : integer; pp, cp : ttreenode; begin if assigned(tree.selected) then begin cp := tree.selected; pp := cp; for i := 1 to round(tree.height/30) do if cp <> nil then begin pp := cp; cp := cp.getprevvisible; end; tree.topitem := pp; end; end;