Афоризм
Наш кот не гадит в туфли, он брезливый.
Наталья Резник
Последние статьи

 • RawContacts
Необработанные контакты в Android
 • javax.crypto.Cypher
Cимметричное шифрование и дешифрирование
 • Random, Math.random
Генерация случайных чисел
 • Компонент JDatePicker
Описание и пример компонента JDatePicker
 • Компонент Tree
Описание и пример дерева Tree библиотеки base-gui
 • Grid с навигатором
Описание и пример Gridp с навигатором
 • Компонент Grid
Описание и пример Grid библиотеки base-gui
 • Библиотека base-gui
Описание компонентов библиотеки base-gui
 • Оператор SELECT
Использование SQL-оператора SELECT
в помощь разработчикам Swing-приложений

Пример использвания дерева Tree

В статье рассмотрен пример (example-tree) создания дерева Tree для иерархического представления набора записей в виде объектов с использованием модуля base-gui. В примере демонстрируются возможности API Tree по добавлению и удалению записей, использования «собственных» иконок, а также callback функция, вызываемая после выделения одной из записей дерева и открывающая окно с сообщением об объекте.

На следующем скриншоте представлен интерфейс примера.

1. Описание примера

Описание главного класса примера ExampleTree будет представлено следующим образом :

  1. Описание внутреннего класса Good;
  2. Поля с данными и метод создания объектов Good;
  3. Формирование интерфейса;
  4. Методы добавления/удаления записей;
  5. Главный класс ExampleTree.

Внутренний класс Good

Внутрений класс Good (товар) расширяет свойства базового класса TreeRecord и используется для загрузки данных в дерево. TreeRecord включает поля 'id', 'pid', 'name' и методы управления полями Get/Set. Класс Good включает дополнительные 2 поля (quantity, cost), определяющие количество и стоимость товара.

class Good extends TreeRecord 
{
    private Float quantity;
    private Float cost    ;

    public Float getQuantity(){
        return quantity;
    }

    public void setQuantity(Float quantity) {
        this.quantity = quantity;
    }

    public Float getСost() {
        return cost;
    }

    public void setСost(Float cost) {
        this.cost = cost;
    }
}

Поля с данными, метод формирования объекта Good

Описание полей класса (см. листинг ниже) включает объект дерева tree, массив данных goods, загружаемый в дерево после инсталляции, массив данных goods_add, загружаемый в дерево при нажатии на кнопку «Добавить запись». Индексный параметр added_idx определяет добавляемую в дерево запись. Путь к файлу с изображением IMG_PATH используется для загрузки в визуализатор дерева изображения, отличного от используемого по умолчанию.

Поля массивов goods и goods_add имеют следующее назначение (отсчет от 0) :

  • 0 – id, идентификатор записи;
  • 1 – pid, идентификатор родительской записи;
  • 2 – name, наименование записи;
  • 3 – quantity, количество;
  • 4 – cost, стоимость.

Идентификаторы id и pid базового класса TreeRecord позволяют определить иерархическую структуру записей.

Для преобразования записей массива типа Object[] в объект Good используется метод createGood.

private ITree tree = null;

private Object[][] goods = 
                   {{ 0, 0, "Список товаров", null, null},
                    { 1, 0, "Продукты"      , null, null},
                    {11, 1, "Хлеб дарницкий",  0.4f, 40f},
                    {12, 1, "Батон нарезной",  0.3f, 32f},
                    {13, 1, "Сметана"       ,  0.3f, 48f},
                    { 2, 0, "Промтовары"    , null, null},
                    { 3, 2, "Для дома"      , null, null},
                    {31, 3, "Лампочки"      ,  35f, 140f},
                    {31, 3, "Батарейки"     ,  45f, 90f},
                    { 4, 2, "Для дачи"      , null, null},
                    {41, 4, "Замок"         , 600f, 600f},
                    {42, 4, "Грабли"        , 290f, 290f}};
private int        added_idx = 0; 
private Object[][] goods_add = 
                   {{ 5, 2, "Инструмент"    , null, null},
                    {50, 5, "Шуруповерт"    , 7800f, 7800f},
                    {51, 5, "Перфоратор"    , 9000f, 9000f}};

private final String IMG_PATH = "images/document.png";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private Good createGood(final Object[] object)
{
    Good good = new Good();
    good.setId      ((int   ) object[0]);
    good.setPid     ((int   ) object[1]);
    good.setName    ((String) object[2]);
    good.setQuantity((Float ) object[3]);
    good.setCost    ((Float ) object[4]);
    return good;
}

Формирование интерфейса

Метод createGUI формирует интерфейс примера. В методе сначала создается компонент дерева, в конструктор которого передается реализация родительского класса (this) для callback-вызова.

private void createGUI()
{
    tree = new Tree(this);

    File file = new File(IMG_PATH);
    if (file.exists()) {
        ImageIcon image = new ImageIcon(IMG_PATH);
        tree.setLeafIcon(image);
    }

    JButton btnAdd = new JButton("Добавить запись");
    btnAdd.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            addRecord();
        }
    });

    JButton btnDel = new JButton("Удалить запись");
    btnDel.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            deleteRecord();
        }
    });
    // Панель кнопок управления
    JPanel pnlButtons = new JPanel();
    pnlButtons.add(btnAdd);
    pnlButtons.add(btnDel);

    Container container = getContentPane();
    container.add(tree.asWidget(), BorderLayout.CENTER);
    container.add(pnlButtons     , BorderLayout.SOUTH);
}

Если имеется файл (IMG_PATH), то вызывается метод дерева setLeafIcon, который загружает изображение в визуализатор дерева для его представления в «листьях» записей.

К кнопкам интерфейса подключаются обработчики событий, связанных с добавлением и удалением записей.

При размещении компонента дерева в интерфейсе используется метод asWidget.

Объект Tree включает метод (API)
• public JComponent asWidget() ,
который «оборачивает» дерево JTree в скроллинг JScrollPane. Для получения объекта дерева JTree необходимо использовать метод getTree().

Методы управления записями

В пример включены два методы добавления и удаления записей.

Листинг метода добавления записи

Метод добавления записи addRecord выполняет две проверки : индексный указатель added_idx не должен выходить за пределы своего массива и первую (нулевую) запись можно добавить только в определенную позицию.

Запись добавляется в дерево методом addNodeObject, который в качестве параметров получает объект и текстовое значение.

private void addRecord()
{
    if (added_idx > (goods_add.length - 1))
        return;
    Good good = (Good)tree.getSelectedNodeObject();
    if (added_idx == 0) {
        if (good.getId() != 2) {
            String title = "Ошибка"; 
            String msg = "Выделите запись 'Промтовары' и "
                       + "нажмите кнопку 'Добавить'";
            JOptionPane.showMessageDialog(ExampleTree.this,
                          msg, title,
                          JOptionPane.INFORMATION_MESSAGE);
        } else {
            good = createGood(goods_add[added_idx]);
            tree.addNodeObject(good, good.getName());
            added_idx++;
        }
    } else {
        good = createGood(goods_add[added_idx]);
        tree.addNodeObject(good, good.getName());
        added_idx++;					
    }
}

Листинг метода удаления записи

Метод удаления записи выполняет проверку наличия дочерних узлов. Запись удаляется, если метод getChildCount вернет значение 0, т.е. скажет об отсутствии «детей». Можно удалить запись из дерева вместе с дочерними; необходимо об этом помнить и синхронизировать удаляемые записи с хранилищем (базой данных).

private void deleteRecord()
{
    // Выделенная запись
    TreeNode node = tree.getSelectedNode();
    if ((node != null) && (node.getChildCount() == 0))
        tree.deleteNodeObject(node);
}

Главный класс ExampleTree

Листинг класса ExampleTree (см. код ниже), не включает поля и методы, описанные выше. Полный исходный код примера можно скачать в конце страницы.

В конструкторе класса создается интерфейс и в дерево загружается набор записей в виде объектов Good. Интерес представляет метод обратного вызова (callback) onClickNode, который вызывается компонентом tree при выделении какой либо записи. Чтобы данная функция «сработала» необходимо в классе (ExampleTree) реализовать интерфейс ITreeListener.

Функция обратного вызова onClickNode передает выделенный объект типа TreeRecord, который приводится к типу Good. А далее по сценарию : формирование текста и отображение сообщения в диалоговом окне JOptionPane окна JFrame.

public class ExampleTree extends JFrame 
                         implements ITreeListener
{
    public ExampleTree() {
        super("Tree example");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        createGUI();
        List<TreeRecord> list;
        list = new ArrayList<TreeRecord>();
        for (int i = 0; i < goods.length; i++) {
            Good good = createGood(goods[i]);
            list.add(good);
        }
        tree.loadData(list);

        setSize(520, 360);
        setVisible(true);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override
    public void onClickNode(TreeRecord record)
    {
        // Выделенный объект
        Good good = (Good)record;
        String title = "Выделенная запись"; 
        String msg = "id=" + good.getId()
                   + ", pid=" + good.getPid()
                   + ", name=" + good.getName();
        JOptionPane.showMessageDialog(ExampleTree.this, 
            "Вы выбрали запись : \n" + msg,
            title, JOptionPane.INFORMATION_MESSAGE);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public static void main(String[] args) {
        new ExampleTree();
    }
}

Старт примера

Архив примера включает командный файл run-example-tree.bat для старта example-tree.jar в Windows из командной строки. Запускаемый example-tree.jar (runable) может быть стартован не только из командной строки, но и обычным способом (двойным нажатием клавишей мыши), поскольку модуль lib/base-gui-1.0.0.jar включен в classpath манифеста META-INF/MANIFEST.MF.

Скачать пример

Архивный файл base-gui-example.zip включает данный пример (example-tree) и другие примеры использования модуля base-gui.

  Рейтинг@Mail.ru