|
|
Наследник
TCustomListView,
аналог
TTreeView.
Основное отличие от стандартного компонента TTreeView - этот компонент предназначен для
визуального отображения
больших древесных структур данных, содержащих от нескольких тысяч
до
миллионов узлов. Стандартный TTreeView
начинает испытывать серьезные проблемы с быстродействием уже при тысяче узлов в
дереве, но самое главное - технически стандартный tree-view-контрол не способен поддерживать деревья с
числом узлов больше 32767 (претензии к MicrosoftTM).
При реализации TFastTreeView, базовый компонент TCustomListView используется сразу
как виртуальный, в виде
таблицы (ViewStyle =
lvsReport). Избыточная функциональность по
возможности скрыта.
Имеется так же некоторое число внешних и функциональных улучшений (по сравнению с TTreeView), такие как прорисовка другим цветом "дорожки" от корневого элемента к текущему выделенному, возможность выделения нескольких узлов в дереве. К сожалению, будучи наследником TCustomListView, компонент FastTreeView не поддерживает экранную анимацию процесса раскрытия/свёртывания узлов. С другой стороны, такая анимация при возникновении тормозов могла бы становиться дополнительным источником раздражения для пользователя.
Компонент разрабатывался для Delphi 5, но работает так же и в Delphi 6, и должен работать в Delphi 7. В более поздних версиях Delphi и его клонов не тестировался.
Подробное описание
По умолчанию, в код данного компонента включается переопределение стандартных имен TTreeView, TTreeNode таким образом, чтобы использование этих имен в модуле, использующем TFastTreeView, перенаправлялось бы на TFastTreeView и TFastTreeItem. Но если добавить в опции проекта символ условной компиляции NOREDECLARETREEVIEW, то такой код включаться не будет, и соответствующие типы придется объявлять полностью.
Внимание (особенность): При использовании TFastTreeView, могла возникать неприятная ситуация, связанная с неправильным помещением первого видимого элемента в неправильную (не первую) позицию после изменения количества видимых элементов в списке (в сторону уменьшения). Такое некорректное поведение полностью "обеспечивается" стандартным list-view контролом (претензии к MicrosoftTM), и полностью устранить его вообще для всех случаев не удается. В случае TFastTreeView эта неприятность устранена, но в связи с этим возникают особенности поведения. А именно: для обеспечения правильного помещения верхнего узла как максимум в первую позицию, перед выполнением свертки узла временно выделенным становится первый узел верхнего уровня (и обеспечивается его "видимость", т.е. сброс в нулевое значение вертикальной линейки прокрутки). После выполнения свертки восстанавливается выделение текущего узла (того, который сворачивается), и так же обеспечивается его видимость. Неприятность заключается в том, что в случае включения свойства MultiSelect, множественное выделение узлов сбрасывается в результате свертки любого узла, и выделенным оказывается только этот узел.
| TFastTreeView | TFastTreeNodes | TFastTreeItem |
Свойства, события и методы класса TFastTreeView, доступные в Инспекторе объектов и во время исполнения.
Свойства, методы, события, совпадающие по смыслу и наименованию с аналогичными свойствами TTreeView (как ближайшего аналога) и TListView (как ближайшего потомка того же родительского класса TCustomListView, от которого произведён TFastTreeView), будут опускаться в данном описании, для сокращения текста. Информация о них может быть получена из справки по Delphi.
Публикуемые
свойства (свойства, которые могут быть изменены Инспектором объектов
в режиме дизайна формы).
| Имя свойства | Тип | Начальное значение |
Описание |
| ButtonImages | TImageList | Если этот список изображений назначен, то в качестве кнопок [-] и [+] перед узлами, которые могут содержать дочерние, используются пиктограммы с индексами соответственно 0 и 1 из этого списка. | |
| FocusedLineColor | TColor | clHighlight | Цвет линии от корневого уровня к текущему узлу в дереве. |
| FocusedLineWidth | Integer | 1 | Толщина линии от корневого уровня к текущему узлу в дереве. |
| LineColor | TColor | clBtnFace | Цвет линии. |
| LineWidth | Integer | 1 | Толщина линии. В случае установки значения в 0, линии не прорисовываются. |
| MultiSelect | Boolean | FALSE | Множественное выделение. Внимание: При схлопывании любого узла, множественное выделение узлов сбрасывается! |
Свойства времени исполнения класса TFastTreeView, доступные из программы (секция PUBLIC).
| Имя свойства | Тип | Только чтение | Описание |
| VisibleItems[ idx: Integer ] | TFastTreeItem | R | Возвращает видимые узлы по индексу в списке только видимых, по индексу от 0 до VisibleItemsCount-1. Под видимыми имеются в виду узлы верхнего уровня, плюс узлы, доступные для фокусировки, т.е., дочерние по отношению к распахнутым родительским узлам, а не те узлы, что визуально вмещаются в окно контрола. |
| Selected | TFastTreeItem | R/W | Возвращает/устанавливает новый выделенный узел. В режиме MultiSelect=TRUE, установка другого узла в качестве выделенного не сбрасывает предыдущие установки. Для сброса текущего множественного выделения следует присвоить предварительно значение NIL этому свойству, затем присваивать новый узел в качестве выделенного. |
Методы класса TFastTreeView, доступные во время исполнения (секция PUBLIC).
| Имя метода | Описание |
| function VisibleItemsCount: Integer; | Возвращает число видимых узлов. Имеются в виду количество узлов верхнего уровня, плюс число узлов, доступных для фокусировки, т.е., дочерних по отношению к распахнутым родительским узлам, а не число узлов, вмещающихся в окно контрола. |
| procedure FullCollapse; | Схлопывает все узлы, на экране остаются только корневые. Подчинённые узлы так же схлопываются, и при последующем раскрытии потребуется последовательное раскрытие всех родительских узлов для того, чтобы добраться до узла нужного уровня. |
| procedure FullExpand; | Раскрывает все узлы, имеющие дочерние. |
| function GetHitTestInfoAt(X, Y: Integer): THitTests; | Получает информацию об узлах, находящихся по указанным (клиентским)
координатам. Результат - множество флажков (т.е. для проверки наличия
флажка требуется использовать конструкция ФЛАЖОК in
GetHitTestInfoA(X, Y), например. htAbove - выше самого
верхнего, |
| function GetNodeAt(X, Y: Integer): TFastTreeItem; | Возвращает узел по заданным (клиентским) координатам или NIL, если по этим координатам узла нет. |
| function AlphaSort: Boolean; | Сортирует узлы дерева в соответствии с правилами (и обработчиками событий) сортировки. На каждом уровне узлы сортируются отдельно. |
| function InheritedNextSelected( Node: TFastTreeItem ): TFastTreeItem; | Возвращает следующий выделенный узел. Метод предназначен для режима MultiSelect = TRUE, в противном случае возвращается NIL, если передан уже селектированный узел. |
Свойства, события и методы класса TFastTreeNodes, доступные во время исполнения.
Для компонента
| Имя свойства или декларация метода | Тип (свойства) | Описание |
| Owner | TFastTreeView | Возвращает ссылку на родительский компонент TFastTreeView. |
| Count | Integer | Общее количество узлов в дереве, считая те, которые невидимы в результате схлопывания родительских узлов. |
| Item[ Idx: Integer ] | TFastTreeItem | Позволяет перечислить все узлы дерева, считая закрытые в результате схлопывания родительских узлов. |
| function Add(Node: TFastTreeItem; const S: string): TFastTreeItem; | Добавление узла. Если параметр Node указан, то узел добавляется в качестве дочернего к нему, иначе - как новый корневой узел. | |
| function AddObject(Node: TFastTreeItem; const S: string; P:Pointer): TFastTreeItem; | Аналогично предыдущему, но узлу сразу приписывается свойство Data, обычно являющееся указателем на объект или запись (структуру в памяти), хотя и не обязательно: точно так же эти данные могут использоваться как числа - всё определяется кодом программы. | |
| function Insert(Node: TFastTreeItem; const S: string): TFastTreeItem; | Вставка узла перед указанным узлом (не должен быть NIL). Узел становится дочерним по отношению к родителю узла Node, либо корневым, если сам узел Node - корневого уровня. | |
| function InsertObject(Node: TFastTreeItem; const S: string; P:Pointer): TFastTreeItem; | То же, что и выше, плюс создаваемому узлу сразу приписываются пользовательские данные, как и в случае AddObject. | |
| function AddChild(Node: TFastTreeItem; const S: string): TFastTreeItem; | Избыточный метод. Дублирует поведение метода Add. | |
| function AddChildObject(Node: TFastTreeItem; const S: string; P:Pointer): TFastTreeItem; | То же, плюс присваивает данные узлу. | |
| function AddChildFirst(Node: TFastTreeItem; const S: string): TFastTreeItem; | Добавляет дочерний узел, помещая его в качестве первого дочернего узла. | |
| function AddChildObjectFirst(Node: TFastTreeItem; const S: string; P:Pointer): TFastTreeItem; | Аналогично предыдущему, плюс приписывание узлу данных пользователя. | |
| procedure Delete( Node: TFastTreeItem ); | Удаляет указанный узел. | |
| procedure Clear; | Удаляет все узлы в дереве. |
Свойства, события и методы класса TFastTreeItem, доступные во время исполнения.
Обратите внимание, что в модуле FastTreeView класс TTreeNode переопределяется как эквивалентный новому классу TFastTreeItem. Это означает, что в коде можно объявлять переменные типа TFastTreeItem как переменные типа TTreeNode, что немного укорачивает запись и позволяет при необходимости возвратиться к использованию стандартного TTreeView (если не использовано слишком большое количество новых возможностей).
Справку по свойствам, выделенным синим цветом, см. в справке Delphi по аналогичному стандартному контролу TTreeView (точнее, по компоненту TTreeNode, аналогом которого является TFastTreeItem).
| Имя свойства / метода | Тип | Атрибуты доступа (для свойств) |
Описание | |
| Count | Integer | R | Возвращает число подчиненных узлов следующего (одного) уровня. | |
| TotalCount | Integer | R | Возвращает общее число подчинённых узлов всех подлежащих уровней. | |
| Owner | TFastTreeView | R | Возвращает ссылку на дерево, которому принадлежит. | |
| Item[ idx: Integer ] | TFastTreeItem | Позволяет перечислить дочерние узлы следующего (одного) уровня по их индексу (от 0 до Count-1) | ||
| function VisibleIndex: Integer; | Возвращает -1, если узел невидим (или невидим один из его пра-родителей) - в результате того обстоятельства, что вышележащий родительский уровень схлопнут. Если же узел видимый, то возвращает его индекс среди всех видимых узлов дерева (быстрая операция). | |||
| HasChildren | Boolean | R/W | Флажок "узел" имеет дочерние узлы. Для ускорения загрузки большого дерева, те узлы, о которых известно, что у них есть дочерние, можно пометить как "имеющие" дочерние узлы без фактического добавления дочерних узлов. Для узлов, имеющих дочерние узлы фактически, возвращает TRUE в любом случае. | |
| Text | String | R/W | ||
| ImageIndex | Integer | R/W | ||
| OverlayIndex | Integer | R/W | ||
| StateIndex | Integer | R/W | ||
| SelectedIndex | Pointer | R/W | ||
| Data | Boolean | R./W | ||
| Collapsed | Boolean | R/W | Противоположно свойству Expanded, TRUE, если узел схлопнут. | |
| Expanded | Boolean | R/W | ||
| procedure Expand( Recurse: Boolean ) | Разворачивает узел. Если параметр Recurse=TRUE, то разворачивает так же все подчинённые узлы рекурсивно на всех нижележащих уровнях. | |||
| procedure Collapse( Recurse: Boolean ); | Схлопывает узел. Если параметр Recurse=TRUE, то схлопывает все нижележащие узлы рекурсивно (иначе, при повторном разворачивании того же узла, те дочерние и подчинённые к ним узлы, что уже были развёрнуты, остаются в прежнем - развёрнутом - состоянии). | |||
| function DisplayRect( TextOnly: Boolean ): TRect; | Возвращает прямоугольник, занимаемый в окне контрола данным узлом. Если параметр TextOnly=TRUE, то возвращается только прямоугольник, занимаемый текстом (без кнопок и пиктограмм). | |||
| Focused | Boolean | R/W | ||
| Selected | Boolean | R/W | ||
| Parent | TFastTreeItem | R | ||
| Visible | Boolean | R/W | Аналогично IsVisible в стандартном TreeView. При присваивании значения TRUE обеспечивается раскрытие всех родительских узлов вышележащих уровней. | |
| function GetFirstChild: TFastTreeItem; | Возвращает первый дочерний узел или NIL, если нет дочерних узлов. | |||
| function GetLastChild: TFastTreeItem; | Возвращает последний дочерний узел или NIL, если нет дочерних узлов. | |||
| function GetNextChild( AfterChild: TFastTreeItem ): TFastTreeItem; | Возвращает следующий дочерний узел. Если AfterChild = NIL, то аналогично GetFirstChild, возвращается первый дочерний. | |||
| function GetPrevChild( BeforeChild: TFastTreeItem ): TFastTreeItem; | Возвращает предыдущий дочерний узел. Если BeforeChild = NIL, то аналогично GetLastChild, возвращается последний дочерний. | |||
| GetNextSibling | TFastTreeItem | R | Возвращает следующий узел того же уровня или NIL, если данный узел является последним дочерним для своего родительского узла. | |
| GetPrevSibling | TFastTreeItem | R | Возвращает предыдущий узел того же уровня или NIL, если данный узел является первым дочерним по отношению к своему родителю. | |
| function GetNext: TFastTreeItem; | Возвращает следующий в дереве узел. Если данный узел является последним дочерним для своего родительского, то происходит подъем по дереву, и вызывается GetNext для родительского узла, пока это возможно. NIL возвращается только для самого последнего узла в дереве. | На самом деле, для FastTreeView эти операции выполняются не путем обхода всего дерева, а практически мгновенно, поскольку внутренним представлением дерева является как раз список всех узлов развернутого дерева, и узлы доступны по их индексам напрямую. | ||
| function GetPrev: TFastTreeItem; | Возвращает предыдущий в дереве узел. Если данный узел является первым дочерним для своего родительского, то возвращается родительский узел. Иначе, прежде чем будет при последовательных вызовах возвращен узел того же уровня, предшествующий родительскому, происходит сначала спуск по дереву и отыскивается самый последний вложенный дочерний для него узел. | |||
| function GetNextVisible: TFastTreeItem; | Возвращает следующий видимый узел. Аналогично GetNext, но узлы, дочерние по отношению к свернутым узлам, пропускаются. | |||
| function GetPrevVisible: TFastTreeItem; | Возвращает предыдущий видимый узел. | |||
| function HasAsParent( Node: TFastTreeItem ): Boolean; | Проверяет, что узел, переданный в качестве параметра, является родителем (или пра-родителем) данного узла на каком-то из вышележащих уровней. | |||
| function HasSiblingsAsParent( Node: TFastTreeItem ): Boolean; | Трудно формулируемо, но примерно так: проверяет, что узел Node и далее лежащие его сестринские узлы содержат данный узел в качестве родительского или пра-родительского на каком-то уровне. Используется внутренним образом при изображении линий дерева, собственно, для этого метод и предназначен. | |||
| function IndexOf( Value: TFastTreeItem ): Integer; | Возвращает индекс (если находит) дочернего узла
нижележащего уровня или |
|||
| procedure MakeVisible; | Обеспечивает видимость данного узла, и его видимость в окне контрола. | |||
| Index | Integer | R | Возвращает глобальный индекс узла в развёрнутом дереве. Этот индекс может использоваться для прямого доступа к узлу свойством TFastTreeNodes.Item[ idx ]; | |
| function NextSelected: TFastTreeItem; | Предназначен для быстрого перечисления выделенных узлов в режиме TFastTreeView.MultiSelect = TRUE | |||
| procedure Delete; | Удаляет узел. Аналогично вызову метода Free. | |||
| procedure DeleteChildren; | Удаляет все дочерние узлы. | |||
| Deleting | Boolean | R | Находится в значении TRUE от момента, когда узел начал разрушаться в результате вызова метода Free. | |
| procedure MoveTo(Destination: TFastTreeItem; Mode: TNodeAttachMode); | Перемещает узел в другое место в дереве (Destination - новый родитель, если NIL - то в корень дерева; Mode - в какое именно место в списке дочек узла Destination) | |||
| procedure Sort( Recurse: Boolean ); | Сортирует подчинённые узлы. Если Recurse = TRUE, то сортируются рекурсивно все подлежащие уровни (но на каждом уровне - сортировка выполняется отдельно для каждого родительского узла). | |||
| function EditLabel: Boolean; | Начинает редактирование текстовой метки узла. Заметьте, что пользователь не может сам начать редактирование метки какими-либо манипуляциями клавиатуры или мыши, если это не предусмотрено в коде разработчика. | |||
Оптимизация
Используйте скобки Items.BeginUpdate / Items.EndUpdate
на время выполнения изменений содержимого дерева. Если этого не делать,
скорость работы может существенно упасть. Пример:
var TV : TFastTreeView;
Node: TFastTreeItem;
......
TV.Items.BeginUpdate;
try
// работаем,
изменяем данные, добавляем/удаляем элементы и т.д.
finally
TV.Items.EndUpdate;
end;
(C) by Vladimir Kladov, 2000-2010