|
||||||||
|
Таблицы. TOutline
TOutline создан для ведения и отображения иерархических структур данных ? деревьев. Это один из наиболее сложных и интересных компонентов. В этот раздел он попал потому, что является потомком таблицы (TCustomGrid), хотя и мало чем ее напоминает. Типичным примером применения TOutiine можно назвать отображение структуры файловой системы (для этого даже есть отдельный компонент TDirectoryOutline). В описанном ниже примере OBJTREE этот компонент используется для отображения дерева классов библиотеки VCL. Дерево состоит из элементов (будем называть их узлами), упорядоченных по уровням. Каждый из них имеет родительский узел (на более высоком уровне) и список дочерних узлов-потомков. Исключением являются корневой узел (нулевого уровня) ? он не имеет предка, и узлы последнего уровня, не имеющие потомков. Каждый узел является объектом класса TOutlineNode:
Рассмотрим сначала методы и свойства этого объекта. С каждым узлом можно связать информацию ? имя и произвольные данные:
Указатель на родительский узел определяется свойством:
Если список дочерних узлов не пуст, что можно проверить при помощи свойства
то для получения информации о них есть методы:
В последних двух методах параметр Value содержит индекс предыдущего найденного потомка. Индекс ? это уникальный идентификатор узла в дереве, определенный свойством:
Используя его, можно получить указатель на узел (см. ниже сам компонент TOutline). Узлы пронумерованы таким образом, что если родитель имеет номер N, то первый из его потомков ? номер (N+1). Можно узнать и полное имя (путь) узла, представляющее собой конкатенацию всех родительских имен и имени узла, разделенных специальным символом. Этот символ определен в свойстве ItemSeparator объекта TCustomOutline, которому принадлежат узлы. Полный путь определяется свойством:
Каждый узел расположен на своем иерархическом уровне. На самом верху находится узел уровня 0. Все другие являются для него дочерними; он не виден и не доступен пользователю. Поэтому на первом доступном уровне ? с номером 1 ? могут находиться по вашему желанию один или несколько узлов. Уровень иерархии узла можно узнать в его свойстве:
Чтобы изменить уровень, надо вызвать метод:
который перемещает узел в список другого уровня. Диапазон перемещения TChangeRange ограничен:
Чтобы переместить узел в дереве, нужно вызвать следующий метод
Он перемещает узел (вместе со всеми потомками) в положение с индексом Destination. Родительский узел н< может переместиться на место любого из своих потомков. Режим перемещения AttachMode означает:
Индекс того из предков узла, который находится в списке самого высокого уровня, известен из свойства:
Для корневого узла это свойство равно 0. Компонент TOutline не только хранит древовидную структуру, он еще и отображает ее. На экране каждый узел может находиться в двух состояниях, свернутом и развернутом. В свернутом состоянии потомки узла не видны, в развернутом они изображаются чуть ниже и правее друг под другом. Состояние узда может иллюстрироваться значком (плюс/минус, открытая/закрытая папка ? см. описание свойства OutlineStyle компонента TOutline). В таблице приведены методы и свойства, управляющие состоянием узла на экране:
Сворачивать/разворачивать узлы дерева, помимо щелчков мышью, можно нажатием клавиш:
Свойство
означает, может ли быть виден узел. Это возможно только в том случае, если видны все его родители. При отрисовке ширина узла сообщается методом:
Теперь перейдем от описания узла к описанию самого дерева ? компонента TOutline. Он представляет собой совокупность узлов типа TOutlineNode. Всего в дереве содержится число узлов, равное значению свойства:
К каждому из них можно обратиться, используя свойство:
На текущий (выделенный) узел можно сослаться через свойство:
Например, выполнение оператора
приведет в развернутое состояние ту часть дерева, в которой находится выделенный узел (начиная от его самого далекого предка TopItem). Свойство
показывает, какая строка дерева в данный момент имеет фокус. Зная "содержимое" узла, то есть его имя или данные, можно найти его в дереве и узнать индекс. Для этого нужно вызвать один из методов, возвращающих его:
Можно найти узел и по координатам точки в клиентской области компонента (на самом деле играет роль только координата Y) с помощью следующего метода:
Целых три пары методов добавляют новый узел в дерево. Его имя инициализируется параметром Text. Различие между первым и вторым методами в парах в том, что второй позволяет связать с узлом данные (параметр Data), а в первом вместо них записывается nil.
? добавляют новый узел в качестве последнего в тот же список, где находится узел Index. Поскольку на самом верху иерархии может быть только один узел, то в случае задания Index = 0 он добавляется в список верхнего уровня. Соответствуют режиму oaAdd;
? добавляют новый узел в качестве последнего потомка узла Index. Соответствуют режиму oaAddChild;
? вставляют узел в положение Index. При этом прежний узел с таким индексом и все другие на этом уровне сдвигаются вниз. Единственное исключение ? задание в качестве параметра нулевого индекса. В этом случае узел добавляется последним в список самого верхнего уровня. Соответствуют режиму oaInsert. Все методы вызывают переиндексирование дерева и возвращают уже новый индекс для вставленного узла. Если нужно удалить узел, то метод
удаляет узел с индексом Index, а метод
очищает все дерево. Если нужно вставить или удалить сразу много узлов и при этом избежать трудоемких операций переиндексации и перерисовки дерева, то соответствующий код надо заключить между вызовами методов:
Первый устанавливает специальное состояние обновления и на время запрещает все пересчеты и перерисовки, а второй сбрасывает его и обновляет дерево. Это состояние можно изменить и при помощи метода:
Дерево можно полностью свернуть или полностью развернуть вызовом методов:
Каждый узел, изменяя свое состояние, предупреждает об этом родительское дерево. В зависимости от того, свернулся он или развернулся, вызываются обработчики событий
где параметр Index означает индекс узла, изменившего состояние. Метод
возвращает ширину, занимаемую изображением узла (если установленный стиль не osOwnerDraw, см. ниже). Дерево может быть загружено и выгружено в поток и файл при помощи методов:
Для прокрутки информации TOutline по умолчанию имеет обе полосы, определяемые свойством:
Строка (символ), разделяющий имена узлов при составлении полного имени узла, содержится в свойстве:
На стадии разработки можно набрать строки, соответствующие будущим узлам дерева, в специальном редакторе. При этом узел попадет на уровень, соответствующий количеству пробелов или знаков табуляции перед его названием. Набранные строки текста содержит свойство:
Это свойство предназначено для использования именно на этапе разработки, так как свойство Items в это время недоступно. Во время исполнения с информацией об узлах нужно работать, используя свойство Items. При рисовании дерева, помимо собственно текста, вместе с ним может изображаться одна из пиктограмм:
Желательно, чтобы картинки имели "прозрачный" фон, то есть чтобы их свойство TransparentColor соответствовало цвету рабочей области компонента. Эти пиктограммы можно переопределить в случае необходимости. Свойство OutlineStyle определяет, в частности, когда и какие пиктограммы будут показаны:
В зависимости от значения этого свойства изображаются:
На внешний вид дерева влияют и опции, содержащиеся в свойстве:
Это множество может содержать элементы:
Рисование дерева по умолчанию осуществляется системой, но может быть возложено и на программиста. Определяется это свойством:
Стиль osStandard подразумевает, что для каждого узла будет изображено то, что предусмотрено стилем OutlineStyle. Для реализации стиля otOwnerDraw нужно нарисовать содержимое узла в обработчике события:
Параметры:
Высота каждого узла постоянна и в этом случае определяется свойством:
Для рисования у компонента есть своя канва:
Установить ее можно только для объекта стиля osOwnerDraw; при osStandard канва игнорируется. Обрамление компонента задается свойством:
Разобраться с применением этого компонента поможет пример OBJTREE. В нем по заранее заданному массиву компонентов ClassesSet выстраивается иерархическое дерево, в которое добавляются и все объекты-предки. Для примера были выбраны только 32 компонента, при желании можно включить и все остальные. Не забывайте при этом добавить содержащие их модули к тем, что содержатся в операторе uses. Когда вы перемещаете фокус по дереву, отображается имя объекта и имя модуля, в котором он описан. Для этого используется информация, возвращаемая недокументированным (пока?) методом класса TObject.ClassInfo. Возвращаемая им структура описана в исходных текстах VCL.
Для комментария : kadan@grsu.grodno.by | |||||||||||||||||||||||||||||
За содержание страницы отвечает Гончарова М.Н. © Кафедра СПиКБ, 2002-2017 |