![]() |
|
||
|
|
|
Древовидные структуры(Андрей Ковалев) SWING - библиотека, основу этой библиотеки составляют визуальные компоненты. Похоже, что большинство компонентов успешно освоены российскими разработчиками, свидетельством тому являются, ссылки на которые размещены в рубрикаторе нашей колонки. Полный перечень компонентов представлен на обучающем сервере Sun. Наиболее сложными из компонентов являются те, которые предназначены для представления сложных структур данных - списков, таблиц и т.п. Например, компонент для представления таблиц JTable для обеспечения полной функциональности и управляемости требует разработки в общей сложности семи классов. В тьюториале этот компонент сопровождается 11 примерами. См. также статью Влада Каменского. Древовидные структуры позволяют наиболее универсальным способом представлять данные и являются при этом очень гибкими. Пример GenealogyTree.java является прекрасным подтверждением сказанному. Полная функциональность дерева JTree в SWING достигается при реализации 10 классов(!). Зато проделав такой регламент работ, разработчик получает возможность эффективно отображать данные и обеспечивать определенными действиями каждый элемент полученной структуры. Прежде всего обратим внимание на иерархию компонентов приложения Java. Пример из тьюториала дает представление об этой иерархии: Анатомия программы на базе компонентов Swing Очевидно, нарисовать вручную иерархию компонентов в контейнере JFrame не просто, тем более, если конструкторы компонентов разбросаны по всему тексту программы на Java. Представим себе, что иерархия является динамической. Задача при этом еще более усложняется. В этой статье мы рассмотрим метод представления иерархии компонентов с помощью дерева.
Для того, чтобы отображать компоненты Swing в виде листьев дерева, надо реализовать
интерфейс, заданный в модели дерева,
и методы поддержки обработчиков событий
Для завершения оформления модели компонентов надо написать конструктор private EventListenerList model_listeners; public void reload()Код функций addTreeModelListener, removeTreeModelListener,
valueForPathChanged очень прост и должен соответствовать требованиям работы
механизма обработки. Поэтому мы можем теперь перейти к целевой логике нашего класса.
Конструктор служит для инициализации переменных, при задании корневого компонента следует
вызвать метод reload() и запомнить новый корневой элемент во внутренней
переменной:
JComponent root_component = (JComponent)new JPanel();
public JComponentTreeModel( JComponent _root ) {
model_listeners = new EventListenerList();
setRootComponent( _root );
}
public void setRootComponent( JComponent _root ) {
if( null != _root )
{
root_component = _root;
reload( );
}
}
public Object getRoot( ) {
return root_component;
}
Метод доступа к корневому элементу открывает группу методов доступа к данным иерархии.
Следующим в группе разработаем метод получения количества подчиненных узлов, который в
нашем пример должен возвращать количество компонентов в контейнере. Таким образом, модель
получает возможность генерировать размеры массивов данных для всех узлов, начиная с
корневого:
public int getChildCount(Object parent) {
if ( null == parent )
return 0;
return ((Container)parent). getComponentCount();
}
Затем, следует перейти к методу, который возвращает один из подчиненных объектов,
принадлежащих данному объекту. При первой итерации, имея корневой контейнер и получив
количество содержащихся в нем компонентов, имеем возможность сканировать все элементы,
последовательно изменяя параметр index от 0 до
getChildCount(parent). Для каждого из получаемых объектов класс
JTree вызовет затем метод с длинным названием
getTreeCellRendererComponent и не менее длинным списком параметров (7 штук).
Этот метод позволяет правильно изобразить значение текущего узла дерева. Простейшая
(default) реализация этого метода (и содержащего его класса) уже существует, поэтому не
станем здесь заострять на нём внимание.
Итак, метод итерирования по узлам выглядит следующим образом:
public Object getChild(Object parent, int index) {
return ((Container)parent). getComponent( index );
}
Итерация заканчивается, если специальный метод говорит, что узел не содержит подчиненных
компонентов:
public boolean isLeaf(Object parent) {
return 0 == getChildCount( parent );
}
Следует отметить, что рассмотренные выше методы являются достаточными для построения
модели. Единственный метод, который осталось реализовать, выполняет поиск индекса
заданного объекта в контейнере:
public int getIndexOfChild(Object parent, Object Child) {
for ( int i=0;
i<
((Container)parent).getComponentCount();
i++)
if( Child == ((Container)parent).getComponent(i) )
return i;
return 0;
}
В заключение сделаем замечание, которое нам надо будет вспомнить в следующей заметке,
посвященной методу отображения информации об узле дерева. Модель является универсальным
интерфейсом между данными и визуальным представлением, поэтому работает с переменными
класса ![]() Рис. 1. Вид компонентного дерева. Мы рассмотрели один из методов создания изображения иерархии в виде дерева, который
заключается в реализации интерфейса модели дерева
22.01.2001 |
| Справка | Условия | |
| В начало | Логин | Комментарий к колонке | Поиск | Почта |