문제

I'm trying to find a solution the problem of collapse in JTree after reload it. The situation:

JTree

[-] Office A
 |---[-] Office A.1
 |    |---[-] Office A.1.1
 |    |---[-] Office A.1.2
[-] Office B
 |---[-] Office B.1
 |    |---[-] Office B.1.1
 |    |    |---[-] Office B.1.1.1

Now I have to add the Office A.1.3. To do this I get the Office A.1 and with the method add(DefaultMutableTreeNode aNode) I add Office A.1.3.

OfficeA1.add(OfficeA13);

After this I call the reload method on the DefaultTreeModel of the tree.

The problem is that after this call the tree collapse all:

[+] Office A
[+] Office B

And I have to manually expand the node Office A to be sure that the node is added...

[-] Office A
 |---[-] Office A.1
 |    |---[-] Office A.1.1
 |    |---[-] Office A.1.2
 |    |---[-] Office A.1.3
[+] Office B

My code...

   DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root not visibile");
   DefaultMutableTreeNode usersRoot = new DefaultMutableTreeNode("Utenti");
   DefaultMutableTreeNode groupsRoot = new DefaultMutableTreeNode("Gruppi");
   DefaultMutableTreeNode officesRoot = new DefaultMutableTreeNode("Uffici")
   root.add(usersRoot);
   root.add(groupsRoot);
   root.add(officesRoot);

   JTree ccTree = new JTree(root);

and when I add node...

Office anOffice = //get the correct office object
DefaultTreeModel model = (DefaultTreeModel)competenzaTree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();

DefaultMutableTreeNode n = (DefaultMutableTreeNode)root.getChildAt(0);

n.add(new DefaultMutableTreeNode(anOffice));
model.reload(n);

The problem is whit the officesRoot node. The usersRoot and groupsRoot node are not hierarchical.

Is there a way to avoid this behavior ? Thanks.

Probably another way to ask can be which is the way to add/remove node from a tree without causing collapse of all tree ?

p.s. I also read this post but it did not help me.

도움이 되었습니까?

해결책

Consider using DefaultTreeModel#insertNodeInto(DefaultMutableNode, DefaultMutableNode, int) which should inform the JTree table that a new node has become available, cause the JTree to be updated, but shouldn't effect the current expanded state of the tree

This example is based on the example found in How to use trees

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

public class TestTree extends JPanel {

    private JTree tree;
    private DefaultTreeModel model;
    private JButton btnAdd;
    private int childCount;

    public TestTree() {
        super(new BorderLayout());

        //Create the nodes.
        DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series");
        createNodes(top);

        model = new DefaultTreeModel(top);

        //Create a tree that allows one selection at a time.
        tree = new JTree(model);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

        //Create the scroll pane and add the tree to it. 
        JScrollPane treeView = new JScrollPane(tree);

        //Add the split pane to this panel.
        add(treeView);

        btnAdd = new JButton("Add");
        btnAdd.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                TreePath treePath = tree.getSelectionPath();
                if (treePath != null) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
                    DefaultMutableTreeNode child = new DefaultMutableTreeNode("Child " + (++childCount));
                    model.insertNodeInto(child, node, node.getChildCount());
                }
            }
        });

        add(btnAdd, BorderLayout.SOUTH);
    }

    private class BookInfo {

        public String bookName;

        public BookInfo(String book) {
            bookName = book;
        }

        public String toString() {
            return bookName;
        }
    }

    private void createNodes(DefaultMutableTreeNode top) {
        DefaultMutableTreeNode category = null;
        DefaultMutableTreeNode book = null;

        category = new DefaultMutableTreeNode("Books for Java Programmers");
        top.add(category);

        //original Tutorial
        book = new DefaultMutableTreeNode(new BookInfo("The Java Tutorial: A Short Course on the Basics"));
        category.add(book);

        //Tutorial Continued
        book = new DefaultMutableTreeNode(new BookInfo("The Java Tutorial Continued: The Rest of the JDK"));
        category.add(book);

        //JFC Swing Tutorial
        book = new DefaultMutableTreeNode(new BookInfo("The JFC Swing Tutorial: A Guide to Constructing GUIs"));
        category.add(book);

        //Bloch
        book = new DefaultMutableTreeNode(new BookInfo("Effective Java Programming Language Guide"));
        category.add(book);

        //Arnold/Gosling
        book = new DefaultMutableTreeNode(new BookInfo("The Java Programming Language"));
        category.add(book);

        //Chan
        book = new DefaultMutableTreeNode(new BookInfo("The Java Developers Almanac"));
        category.add(book);

        category = new DefaultMutableTreeNode("Books for Java Implementers");
        top.add(category);

        //VM
        book = new DefaultMutableTreeNode(new BookInfo("The Java Virtual Machine Specification"));
        category.add(book);

        //Language Spec
        book = new DefaultMutableTreeNode(new BookInfo("The Java Language Specification"));
        category.add(book);
    }

    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event dispatch thread.
     */
    private static void createAndShowGUI() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }

        //Create and set up the window.
        JFrame frame = new JFrame("TreeDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add content to the window.
        frame.add(new TestTree());

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event dispatch thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top