Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Metoda_OOP.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.71 Mб
Скачать

4.2.3Пользовательский интерфейс

Для демонстрации работоспособности созданных классов, необходимо создать тестовую программу. Пример пользовательского интерфейса приведен на рисунке 4.3.

Рисунок 4.3 – Пример реализации пользовательского интерфейса

Для демонстрации работы списков выбираем компонент графической библиотеки swing - JTree. Для добавления элементов в список используется дополнительный класс TreeModel. Существуют готовые модели работы с деревом, сама простая из них модель “по умолчанию” – DefaultTreeModel.

В дереве JTree отсутствует прокрутка, поэтому для организации прокрутки его необходимо разместить в панели прокрутки JScrollPane и все детали будут обработаны автоматически.

Полный набор всех компонент используемых в тестовой программе приведен на рисунке 4.4. Обратите внимание на количество контейнеров типа JPanel. Они используются для размещения всех визуальных компонент с указанием конкретного типа Layout.

Swing представляет собой своего рода библиотеку или пакет классов, позволяющих пользователю программировать развитый графический интерфейс пользователя (GUI) на современном уровне.

Основным компонентом GUI является JFrame – базовый класс для окна.

Для размещения (группировки) объектов на JFrame используются объекты класса JPanel.

Класс JPanel пакета Swing представляет собой в чистом виде контейнер, предназначенный для размещения внутри себя других элементов, в том числе и других панелей. Панели - очень удобное средство для организации сложных GUI-интерфейсов, содержащих большое количество управляющих элементов, которые можно объединять в функциональные группы и потом размещать в удобном месте приложения.

По умолчанию сами панели визуально никак не проявляют себя на экране, кроме цвета непрозрачного по умолчанию фона (background). Однако к ним можно добавить видимую рамку (с заголовком или без). Для добавления компонентов в панель используется метод add().

Рисунок 4.4 – Перечень всех компонентов тестовой программы

С панелями (и другими контейнерами) тесно связано использование специальных классов, так называемых менеджеров расположения (layout managers), которые позволяют автоматически определять местоположение и размеры компонентов внутри панели. Существует несколько типов менеджеров расположения, каждый из которых растягивает (сжимает) и раскидывает добавляемые в панель элементы по определенному правилу. В Java используются следующие типы менеджеров расположения:

  • BorderLayout. - предназначен для расположения 5-ти элементов, располагающихся, соответственно, в центре панели и по 4-м сторонам света (запад, восток, север, юг). Часто используется для приложений, выводящих основную информацию в центре, а боковые полосы использующих для различного рода кнопочек или строк состояния. Размеры каждой из этих 5-ти частей задаются автоматически пропорционально размеру панели.

  • FlowLayout. - самый примитивный менеджер, который располагает, последовательно добавляемые элементы друг за другом в одну строчку с переносом на следующую, если уже не хватает места. Размеры элементов автоматически растягиваются так, чтобы заполнить всю панель.

  • GridLayout. - решеточный менеджер, располагающий элементы в виде таблицы с заданным пользователем числом строк и столбцов. Размеры всех ячеек при этом одинаковые, а размер добавляемых элементов подгоняется под размер ячейки.

  • CardLayout. - менеджер, который располагает элементы в виде колоды карт, при этом виден на экране только последний. Размер каждого элемента растягивается на всю панель. Для последовательного просмотра (открытия) каждого элемента используются его методы next() и previous().

  • BoxLayout. - аналог FlowLayout, но располагающий элементы в направлении задаваемом пользователем (X-горизонталь или Y-вертикаль). В отличие от GridLayout, здесь каждый элемент может занимать ячейку различного размера.

  • GridBagLayout. - более "умный" решеточный менеджер, позволяющий, задавать индивидуальные свойства каждой ячейки (размер, поля), а также объединять несколько ячеек для расположения какого-нибудь большого элемента. Все правила размещения компонентов задаются в объекте другого класса, GridBagConstraints.

Класс GridBagConstraints содержит одиннадцать полей, определяющих размеры компонентов, их положение в контейнере и взаимное положение, и несколько констант — значений некоторых полей. Они перечислены в таблице 5.1. Эти параметры определяются конструктором, имеющим одиннадцать аргументов. Второй конструктор — конструктор по умолчанию — присваивает параметрам значения, заданные по умолчанию.

Дерево

Класс Swing JTree предназначен для отображения структурированных данных, иерархически организованных в виде дерева. Так же как и JTable класс дерева JTree не содержит данные непосредственно в себе, а только отображает их. Само дерево состоит из множества узлов, организованных в многоуровневую древовидную структуру.

Узел представлен специальным классом DefaultMutableTreeNode. Всегда существует единственный корневой узел (нулевой уровень). Корневой узел может непосредственно порождать дочерние узлы первого уровня. Затем каждый дочерний узел в свою очередь может порождать свои дочерние узлы уже второго уровня, являющиеся внуками по отношению к корню и т.д. Количество уровней не ограничивается. Условно принято называть узлы, которые имеют детей, ветвями (branches), а узлы, не имеющие детей, листьями (leaves). Каждый узел связан с определенным объектом (любого типа), который является аргументом конструктора класса DefaultMutableTreeNode(Object obj) .

Таблица 4.1Поля класса GridBagConstraints

Поле

Значение

anchor

Направление размещения компонента в контейнере. Константы:

CENTER, NORTH, EAST, NORTHEAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, и NORTHWEST; no умолчанию CENTER

fill

Растяжение компонента для заполнения ячейки. Константы: NONE, HORIZONTAL, VERTICAL, BOTH; ПО умолчанию NONE

gridheight

Количество ячеек в колонке, занимаемых компонентом. Целое типа int, по умолчанию 1. Константа REMAINDER означает, что компонент займет остаток колонки, RELATIVE — будет следующим по порядку в колонке

gridwidth

Количество ячеек в строке, занимаемых компонентом. Целое типа int, по умолчанию 1. Константа REMAINDER означает, что компонент займет остаток строки, RELATIVE — будет следующим в строке по порядку

gridx

Номер ячейки в строке. Самая левая ячейка имеет номер 0. По умолчанию константа RELATIVE, что означает: следующая по порядку

gridy

Номер ячейки в столбце. Самая верхняя ячейка имеет номер 0. По умолчанию константа RELATIVE, что означает: следующая по порядку

insets

Поля в контейнере. Объект класса insets;по умолчанию объект с нулями

ipadx, ipady

Горизонтальные и вертикальные поля вокруг компонентов; по умолчанию 0

weightx,

weighty

Пропорциональное растяжение компонентов при изменении размера контейнера; по умолчанию 0,0

Множество всех этих объектов для всех узлов и представляет собой, собственно, данные. Ветви могут иметь любое количество детей. Пользователь, щелкнув мышью по ветви, может раскрыть ее или свернуть, делая видимыми или невидимыми детей данной ветви. По умолчанию дерево вначале отображается со всеми свернутыми ветвями, кроме корня.

Процесс свертки и развертки ветви трактуется как событие, которое можно соответствующим образом программно обработать.

Программно процесс создания дерева очень прост и состоит из следующих шагов:

  • Создается корневой узел (в единственном экземпляре) DefaultMutableTreeNode root = new DefaultMutableTreeNode(Object);

  • Создаются узлы первого уровня DefaultMutableTreeNode a1 = new DefaultMutableTreeNode(Object); DefaultMutableTreeNode a2 = new DefaultMutableTreeNode(Object); ... DefaultMutableTreeNode an = new DefaultMutableTreeNode(Object); и добавляются в корень (связываются с ним) root.add(a1); root.add(a2); ... root.add(an);

  • Создаются узлы второго уровня и добавляются в узлы первого уровня в соответствии со структурой строящегося дерева. Процесс продолжается аналогичным образом, пока не будет достигнут самый нижний уровень.

  • Последний этап - это создание объекта "дерево" и загрузка его в контейнер для отображения. JTree tree = new JTree(root); JScrollPane treeView = new JScrollPane(tree);

Когда дерево построено, пользователь может мышью выбрать любой узел. Процесс выбора трактуется, как событие и может быть обработан программно.

Для обработки события выделения элемента дерева необходимо добавить следующий код:

jTree.addTreeSelectionListener(new TreeSelectionListener(){

public void valueChanged(TreeSelectionEvent e) {

DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();

if (node == null)return;

// получили данные, хранящиеся в выделенном узле

Object nodeInfo = node.getUserObject();

}

}

);

jTreeэкземпляр класса JTree

Для отображения узлов дерева LinkedTree необходимо реализовать класс модели дерева, например, LinkedTreeModel как производный от TreeModel. В этом классе объявлены все методы, с помощью которых компонент JTree осуществляет доступ к узлам.

/**

* LinkedTreeModel.java

*/

package stu.jtap.labs.lab4;

public class LinkedTreeModel implements TreeModel {

private LinkedTree tree = null;

private Vector<TreeModelListener> treeModelListeners = new Vector<TreeModelListener>();

/**

* Create tree model on the basis of existent linked <b>tree</b>

* @param tree existing linked tree

*/

LinkedTreeModel(LinkedTree tree){

if(tree==null)

throw new NullPointerException();

this.tree = tree;

}

/**

* Create tree model with root <b>node</b>

* @param node root node

*/

LinkedTreeModel(LinkedNode node){

tree = new LinkedTree(node);

}

/**

* Create tree model with root node containing this data

* @param data root node data

*/

LinkedTreeModel(Object data){

tree = new LinkedTree(data);

}

public Object getRoot() {

return tree.getRoot();

}

public Object getChild(Object parent, int index) {

LinkedNode node = (LinkedNode)parent;

return node.getChildAt(index);

}

public int getChildCount(Object parent) {

LinkedNode node = (LinkedNode)parent;

return node.getChildCount();

}

public boolean isLeaf(Object node) {

return ((LinkedNode)node).isLeaf();

}

public void valueForPathChanged(TreePath path, Object newValue) {

// this is stub method

// not used by this model

}

public int getIndexOfChild(Object parent, Object child) {

LinkedNode node = (LinkedNode)parent;

return node.getIndexOfChild((LinkedNode) child);

}

public void addTreeModelListener(TreeModelListener l) {

treeModelListeners.addElement(l);

}

public void removeTreeModelListener(TreeModelListener l) {

treeModelListeners.removeElement(l);

}

}

Для создания дерева работающего с моделью необходимо объекту класса JTree установить модель вызвав метод setModel() с параметром - объектом класса LinkedTreeModel.

private LinkedTree tree = null;

private LinkedNode selectedNode = null;

/**

* Initialize tree model

* @return void

*/

public void initializeTree(){

tree = new LinkedTree("Root");

tree.getRoot().addSon("First son");

tree.getRoot().addSon("Second son");

LinkedTreeModel model = new LinkedTreeModel(tree);

getJTree().setModel(model);

}