Додавання та видалення вузлів з JTree

У мене є дуже базовий JTree . Коли я в спеку, я вважаю за краще не використовувати TreeModel , якщо вона не потрібна. Я написав SSCCE, щоб виявити проблему:

Іноді я додаєте вузол. Інколи я їх видаляю. Коли я натискаю Add , вузол буде правильно додано. Коли я натискаю Remove , він повинен видалити вузол, але це не так. Крім того, якщо я намагаюся додати більше одного вузла, дерево залишається лише з першим доданим вузлом.

Я написав метод оновлення для JTree , де я спочатку стираю всі вузли, що висять з кореневого вузла, а потім я дивлюся, які вузли та під-вузли я повинен створити.

Що я роблю неправильно тут, крім того, що не використовую TreeModel , щоб керувати деревом?

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;


public class TreeTest {
    private JFrame myFrame;
    private JTree myTree;
    private JButton addButton, removeButton;

    private int numberOfNodes;
    private DefaultMutableTreeNode rootNode;

    private ArrayList graphicIDS;
    private ArrayList graphicInfo;

    public static void main (String [ ] args){
        new TreeTest();
    }

    public TreeTest() {
        graphicIDS = new ArrayList();
        numberOfNodes = 0;
        graphicInfo = new ArrayList();
        graphicInfo.add("Info A");
        graphicInfo.add("Info B");
        graphicInfo.add("Info C");
        graphicInfo.add("Info D");

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        myFrame = new JFrame("JTree test");
        myFrame.setResizable(false);
        myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.NORTH;
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 2;
        c.insets = new Insets(5,5,5,5);

        rootNode = new DefaultMutableTreeNode("Root node");
        myTree = new JTree(rootNode);
        myTree.setPreferredSize(new Dimension(200, 500));
        panel.add(myTree, c);

        c.gridwidth = 1;
        c.gridy++;
        removeButton = new JButton("Remove");
        removeButton.setEnabled(false);
        removeButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {    
                System.out.println("Removed curve "+(graphicIDS.size()));
                graphicIDS.remove(graphicIDS.size()-1);
                numberOfNodes--;
                updateMeasurementsTree();
            }
        });
        panel.add(removeButton, c);

        c.gridx++;
        addButton = new JButton("Add");
        addButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {
                graphicIDS.add("Curve "+(numberOfNodes+1));
                System.out.println("Added curve "+(numberOfNodes+1));
                numberOfNodes++;
                updateMeasurementsTree();
            }
        });
        panel.add(addButton, c);

        myFrame.getContentPane().add(panel);
        myFrame.pack();
        myFrame.setVisible(true);
    }

    public void updateMeasurementsTree(){
        rootNode.removeAllChildren();

        for(int i=0; i< myTree.getRowCount()) {
          myTree.expandRow(row);
          row++;
        }
    }
}
19
Бути "поспіхом" може сповільнити вас; Використання моделі, як вважає @camickr, є правильним підходом. +1, btw, для повного прикладу.
додано Автор trashgod, джерело
поспішайте чи ні, ви майте , щоб повідомити модель, якщо ви зміните вузли під ногами. Не обійтися. @camickr показує, як це робиться, прикрашений мій коментар :-)
додано Автор kleopatra, джерело

1 Відповіді

Я не знаю, чому ви видаляєте і відновлюєте всі вузли.

Оновлення завжди слід робити за допомогою моделі. У вас є пара варіантів:

Оновити модель безпосередньо:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
model.insertNodeInto(new DefaultMutableTreeNode("another_child"), root, root.getChildCount());

Оновити вузли дерева, а потім повідомити модель:

DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
root.add(new DefaultMutableTreeNode("another_child"));
model.reload(root);

Те саме стосується і видалення вузлів.

DefaultTreeModel має removeNodeFromParent (...) , який буде оновлювати модель безпосередньо.

Або ви можете скористатися методом видалення (...) класу DefaultMutableTreeNode. У такому випадку вам знадобиться перезавантажити ().

46
додано
Як щодо видалення дитини значення?
додано Автор Nitesh Verma, джерело
Велике спасибі, я зробив це набагато складніше, ніж це було насправді
додано Автор Roman Rdgz, джерело
Дякую. Мені потрібно грати з JTree ще :)
додано Автор camickr, джерело
+1 - приймати для перезавантаження ;-) Модель має вузли, де введеноРечовина/Змінено - не називайте мене на іменах eact, хоча) повідомляти своїх слухачів після факту. Перезавантажити - останній захід, f.i. після виконання складних модифікацій на декількох глибинах дерева
додано Автор kleopatra, джерело
для з'ясування; при видаленні вузлів метод nodeChanged() викликає помилку поведінки, reload() відмінно працює. це тому, що nodeChanged() не згортає дерева, reload() робить.
додано Автор glend, джерело
ІТ КПІ - Java
ІТ КПІ - Java
436 учасників