- •Лабораторная работа
- •Применение компонента TreeView позволяет информативно представить структуру документа.
- •Модель документа, использующая b-дерево, является универсальной моделью, описывающей различные структуры документов.
- •Разработанный проект является базовым проектом и может быть сохранен в среде Delphi в Repository в качестве шаблона.
Лабораторная работа
(Визуальное построение B-дерева в компоненте TreeView)
Постановка задачи
Пусть у нас существует главная таблица индексов Ti, описывающая некоторую аналитику документа. Структура данных таблицы реализована классическим B- деревом, где каждая запись представлена полями:
ID — номер текущей записи;
ParentID — номер родительской записи, которой принадлежит текущая запись;
Name — название записи (узла).
Нашей задачей является создание дешифратора (вычислителя узлов и ветвей дерева – парсера), отображающего данные в виде древовидной структуры, подобной проводнику Windows, а также интерактивное (визуальное) построение древовидной структуры документа, соответствующего его аналитике.
Алгоритм реализации парсера
Определим, что корнем или корнями документа отношения ParentID:ID, при:
ParentID=0 и ID = 1,2,3,…,n-1,n.
Равенство значений параметра ParentID = ParentID определяет, новый узел или достраиваемую ветвь, то есть ветвь, к какой отыскиваются дочерние ветви.
Условием идентификации корней является условие, при котором над головным узлом нет других узлов:
IF Node = nil Then ID:=0 Else ID:=Integer(Node.Data).
Для каждой записи набора данных Ti формируется ветвь, отображающая в построителе дерева TreeView созданную или раскрытую дочернюю ветвь (узел):
TreeView.Items.AddChildObject(Node, Ti.FieldByName('Name').AsString ,
Pointer(Ti.FieldByName('ID').AsInteger));
при этом для раскрытия узла создается фиктивная ветвь:
TreeView.Items.AddChildObject(TreeNode , '' , nil);
которая, в последующем удаляется:
IF Node.getFirstChild.Data = nil Then Node.DeleteChildren.
Выполнение работы
Дизайн проекта
Создайте новый проект и сохраните его под именем Unit –> TreeUnit, Project –> B_Tree.
Измените имя формы на FormTree.
Установите в форму элементы управления и компоненты доступа к данным (рис.1):
ImageList;
TreeView, изменив имя на TVC, свойство Align := alLeft, выбрав в свойствах Images и StateImages значение ImageList1;
Splitter, установив свойство Align := alLeft;
Panel, установив свойство Align := alClient;
DBGrid, установив свойство Align := alTop;
MainMenu;
PopupMenu1, который свяжите с TVC (TreeView), выбрав в TVC в свойстве PopupMenu значение PopupMenu1;
ClientDataSet, изменив имя на CDS и DataSource1, изменив имя на DS.
Рис. 1 Расположение компонентов в форме |
4. Опишите в редакторе полей CDS(ClientDataSet) следующую структуру полей таблицы:
ID — номер узла, тип поля AutoInc;
ParentID — номер родительского узла, тип поля Integer;
Name — название узла, тип поля String(25).
5. Создайте для CDS доменную структуру, выполнив команду контекстного меню Create Data Set.
6. Сохраните бинарный cds файл в папке проекта под именем TreeNode.cds.
7. Свяжите CDS файлом TreeNode.cds посредством свойства FileName.
8. Свяжите компоненты DS->CDS, DBGrid1->DS, посредством свойств DataSet и DataSource, соответственно.
9. Выберите в форме ImageList1, выполните двойной щелчок мышью по компоненту и добавьте в него картинки (рис. 2), которые в дальнейшем будут отображать узлы дерева.
10. Сохраните проект и скомпилируйте приложение.
Рис. 2 Картинки узлов дерева |
Разработка методов построения дерева
Создайте собственные методы построения дерева и объявите глобальную переменную доступа к файлу:
ExpandLevel - Раскрытие ветвей дерева (рис. 3);
RebuildTree - Построение дерева (рис. 4).
LocalFile: String; - Путь к локальному файлу TreeNode.cds;
Созданные методы должны быть декларированы в разделе Private (рис. 5).
Рис. 3 Метод раскрытия ветвей дерева |
Рис. 4 Метод построения дерева |
Рис. 5 Декларирование методов |
Скомпилируйте приложение.
В обработчике события формы вызовите метод построения дерева (рис. 6).
Рис. 6 Вызов метода построения дерева при создании формы |
В обработчике события onChange компонента TVC (TreeView) создайте метод обмена данными при навигации по дереву (рис. 7).
Рис. 7 метод обмена данными при навигации по дереву |
Скомпилируйте приложение.
В обработчике события onExpanding компонента TVC (TreeView) создайте метод раскрытия ветви при навигации по дереву (рис. 8).
Рис. 8 Метод раскрытия ветви при навигации по дереву |
Скомпилируйте приложение.
Компонент TreeView позволяет эффективно редактировать имена узлов в интерактивном режиме, без применения дополнительных команд, путем выполнения щелчка мышью по отображаемому значению атрибута. Поэтому целесообразно реализовать метод редактирования записей в событиях компонента.
В обработчике события onEdited компонента TVC (TreeView) создайте метод обмена данными с таблицей CDS при редактировании названий узлов дерева (рис. 9).
Рис. 9 Метод обмена данными с таблицей CDS при редактировании названий узлов дерева |
Скомпилируйте приложение.
Создание элементов дерева целесообразно реализовать путем описания отдельных команд контекстного меню для корневых и дочерних элементов, а свертку и развертку дерева путем описания команд главного меню приложения.
Создайте пункт контекстного меню (компонент PopupMenu1) AddRoot – “Добавить корневой элемент” и метод выполнения команды (рис. 10).
Рис. 10 Метод выполнения команды AddRoot – “Добавить корневой элемент” |
Скомпилируйте приложение.
Выполните несколько раз команду “Добавить корневой элемент” (рис. 11).
Рис. 11 Вид приложения после добавления корневых элементов |
Проверьте выполнение команды интерактивного редактирования названия элемента для чего:
выберите в окне корневой элемент, например: КОРЕНЬ 2;
выполните по нему одиночный щелчок мышью;
после предоставления доступа измените название элемента (рис. 12).
Рис. 12 Вид приложения после редактирования элемента |
Для реализации команды “Добавить дочерний элемент” необходимо создать личный метод FocusLevel – передача фокуса на новый узел (рис. 13), который декларируется в разделе Private (рис. 14).
Рис. 13 Метод передачи фокуса на новый узел |
Рис. 14 Декларирование метода |
Скомпилируйте приложение.
Создайте пункт контекстного меню (компонент PopupMenu1) AddChild – “Добавить дочерний элемент” и метод выполнения команды (рис. 15).
Рис. 15 Метод выполнения команды AddChild – “Добавить дочерний элемент” |
Скомпилируйте приложение.
Проверьте правильность работы метода для чего, несколько раз выполните команду “Добавить дочерний элемент” для каждого корневого и вновь созданного дочернего элементов (рис. 16).
Рис. 16 Вид приложения после добавления дочерних элементов |
Создайте пункт контекстного меню (компонент PopupMenu1) DelElement – “Удалить элемент” и метод выполнения команды (рис. 17).
Рис. 17 Метод выполнения команды DelElement – “Удалить элемент” |
Скомпилируйте приложение.
Выполните несколько раз команду “Удалить элемент” (рис. 18).
Рис. 18 Вид приложения после выполнения команды ”Удалить элемент” |
Создайте в главном меню пункты File (Файл) и View (Вид). Для пункта меню Файл создайте команду New (Новый), а для пункта меню Вид создайте команды Collaps (Свернуть дерево), Expanded (Раскрыть дерево), Collaps (Свернуть дерево) и ViewChildNode (Раскрыть дочернюю ветвь).
Для команд Collaps и Expanded напишите соответствующие методы (рис. 19).
Рис. 19 Методы Collaps и Expan |
Для реализации команды ViewChildNode создайте метод, раскрывающий в Grid'е список дочерних ветвей выбранного узла (рис. 20).
Рис. 20 Методы раскрытия дочерней ветви |
Опишите метод реализации команды создания нового документа New с выводом диалога предупреждения (рис. 21).
Рис. 21 Метод создания нового документа |
Скомпилируйте приложение и проверьте выполнение команд.
Комплексная проверка разработанных методов
Создайте новый однокорневой документ ”ПРЕДПРИЯТИЕ” (рис. 22).
Рис. 22 Однокорневой документ ”ПРЕДПРИЯТИЕ” |
Создайте многокорневой документ ”ВУЗ” (рис. 23).
Рис. 23 Многокорневой документ ”ВУЗ” |
Выводы