Философия Java

Деревья


Использование JTree может быть также просто, как об этом сказано:

add(new JTree( new Object[] {"this", "that", "other"}));

Так отображается примитивное дерево. Однако API для деревьев достаточно обширно — несомненно, одно из самых больших в Swing. Это означает, что вы можете делать с деревьями все, что угодно, но более изощренные задачи могут требовать немного исследований и экспериментов.

К счастью, библиотека обеспечивает ядро: компонент дерева “по умолчанию” обычно делает то, что вам надо. Так что большую часть времени вы будете использовать эти компоненты, и только в специальных случаях вам нужно будет исследовать и понимать деревья более глубоко.

Следующий пример использует компонент дерева “по умолчанию” для отображения дерева в апплете. Когда вы нажмете кнопку, добавится новое поддерево в текущей выделенной ноде (если нода не выбрана, используется корневая нода):

//: c13:Trees.java

// Простой пример Swing дерева. Деревья могут

// быть сделаны намного более сложными, чем здесь.

// <applet code=Trees

// width=250 height=250></applet>

import javax.swing.*; import java.awt.*; import java.awt.event.*; import javax.swing.tree.*; import com.bruceeckel.swing.*;

// Берется массив Strings и создается первый

// элемент ноды, а оставшиеся оставляются:

class Branch { DefaultMutableTreeNode r; public Branch(String[] data) { r = new DefaultMutableTreeNode(data[0]); for(int i = 1; i < data.length; i++) r.add(new DefaultMutableTreeNode(data[i])); } public DefaultMutableTreeNode node() { return r; } }

public class Trees extends JApplet { String[][] data = { { "Colors", "Red", "Blue", "Green" }, { "Flavors", "Tart", "Sweet", "Bland" }, { "Length", "Short", "Medium", "Long" }, { "Volume", "High", "Medium", "Low" }, { "Temperature", "High", "Medium", "Low" }, { "Intensity", "High", "Medium", "Low" }, }; static int i = 0; DefaultMutableTreeNode root, child, chosen; JTree tree; DefaultTreeModel model; public void init() { Container cp = getContentPane(); root = new DefaultMutableTreeNode("root"); tree = new JTree(root); // Это добавляется для заботы о скроллировании:


cp.add(new JScrollPane(tree), BorderLayout.CENTER); // Получение модели дерева:

model =(DefaultTreeModel)tree.getModel(); JButton test = new JButton("Press me"); test.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ if(i < data.length) { child = new Branch(data[i++]).node(); // Что было последним, на чем вы щелкнули?

chosen = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if(chosen == null) chosen = root; // Модель будет создавать

// соответствующие события. В ответ

// дерево будет обновлять себя:

model.insertNodeInto(child, chosen, 0); // Здесь помещается новая нода

// в текущую выбранную ноду.

} } }); // Изменение цвета кнопки:

test.setBackground(Color.blue); test.setForeground(Color.white); JPanel p = new JPanel(); p.add(test); cp.add(p, BorderLayout.SOUTH); } public static void main(String[] args) { Console.run(new Trees(), 250, 250); } } ///:~

Первый класс, Branch, это инструмент для получения массива String и построения DefaultMutableTreeNode с первым элементом String в качестве корня, а другие элементы не трогаются. Затем может быть вызван node( ) для производства корня этого “branch”.

Класс Trees содержит двумерный массив из String, из которого могут быть сделаны Branch (ветви), и static int i для подсчета в массиве. Объект DefaultMutableTreeNode содержит ноды, а физическое представление на экране управляется JTree и ассоциированной с ним моделью - DefaultTreeModel. Обратите внимание, что когда JTree добавляется в апплет, он оборачивается в JScrollPane — это все, что нужно сделать для автоматического скроллинга.

JTree управляется своей моделью. Когда вы делаете изменения в модели, модель генерирует событие, которое является причиной того, что JTree выполняет необходимые обновления для отображения представления дерева. В init( ) модель захватывается вызовом getModel( ). Когда нажимается кнопка, создается новая “ветвь(branch)”. Затем находится текущий выделенный компонент (или используется корень, если ничего не выбрано) и метод модели insertNodeInto( ) выполняет всю работу по изменению дерева и является причиной его обновления.

Пример, подобный приведенному мной выше, может дать вам то, что вы хотите от дерева. Однако деревья имеют мощь для выполнения всего, что вы можете вообразить — везде, где вы видите слова “по умолчанию” в приведенном выше примере, вы можете заменить своим собственным классом для получения другого поведения. Но остерегитесь: почти все классы имеют большие интерфейсы, так что вы можете потратить много времени на борьбу с пониманием интерфейсов деревьев. Несмотря на это, в этом заключается хороший дизайн, а альтернативы обычно хуже.


Содержание раздела