How can I refresh a JTree after adding some nodes to the underlying model?

前端 未结 8 2079
情歌与酒
情歌与酒 2020-12-08 21:42

First of all, let me say that I dont use the DefaultTreeModel. I implement my own TreeModel, so i cant use the DefaultXXX stuff. The problem is this: Through some addStuff()

相关标签:
8条回答
  • 2020-12-08 22:09

    Yesterday I struggeled around to fix the same issue. The requirement was to insert and remove nodes on the fly, without collapsing the the expanded tree nodes. I browsed the web and found a bunch of possible solutions, until I stumbled over this thread. Then I applied the anwser from 'Dmitry Frank' with the TreeModelEvent. I was a bit confused, why it is such a big issue to just insert or remove a simple node and let the rest of the JTree untouched! Finally the plain vanilla examples from java2s helped me to find the probably simplest solution at all. (Neither a call like: nodeStructureChanged, nodeChanged, nodesWereRemoved, nodesWereInserted, etc. nor a TreeModelEvent like suggested by 'Dmitry Frank' was required.)


    Here's my solution:

    // Remove a node
    treeModel.removeNodeFromParent(myNode);
    
    // Insert a node (Actually this is a reinsert, since I used a Map called `droppedNodes` to keep the previously removed nodes. So I don't need to reload the data items of those nodes.)
    MyNode root = treeModel.getRootNode();
    treeModel.insertNodeInto(droppedNodes.get(nodeName), root, root.getChildCount());
    

    Keep it simple ;)

    0 讨论(0)
  • 2020-12-08 22:11

    I've always found the TreeModel a bit confusing. I agree with the above statement that the model should notify the view when a change is made so the view can repaint itself. However, this does not seem to be the case when using the DefaultTreeModel. I find you need to invoke the reload() method after updating the model. Something like:

    DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
    DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
    root.add(new DefaultMutableTreeNode("another_child"));
    model.reload(root);
    
    0 讨论(0)
  • 2020-12-08 22:12

    It seems to be possible to reinitialize the whole tree by setting the model to null: e.g.

            TreePath path = tree.getSelectionPath();
            model.doChanges(); // do something with model
            tree.setModel(null);
            tree.setModel(model);
            tree.setSelectionPath(path);
            tree.expandPath(path);
    

    Tree update works for me

    kr Achim

    0 讨论(0)
  • 2020-12-08 22:12

    For example:Jtree Refresh Dynamically

    package package_name;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    
    public final class homepage extends javax.swing.JFrame implements ActionListener
    {
         DefaultTreeModel model;
         DefaultMutableTreeNode root;
         File currentDir = new File("database");
    
    public homepage() throws InterruptedException {
            initComponents();
        //------full screen window
            this.setExtendedState(MAXIMIZED_BOTH);
        //====================Jtree Added Details..   
    
        //result is the variable name for jtree
            model =(DefaultTreeModel) treedbnm.getModel();
        //gets the root of the current model used only once at the starting
            root=(DefaultMutableTreeNode) model.getRoot();
        //function called   
            dbcreate_panel1();
            Display_DirectoryInfo(currentDir,root);
    
    }//End homepage() Constructor
    public void Display_DirectoryInfo(File dir,DefaultMutableTreeNode tmp_root) throws InterruptedException 
    {..........   
    }
    public void dbcreate_panel1()
    {
        //------------------Jtree Refresh Dynamically-------------------//
                 root.removeFromParent();
                 root.removeAllChildren();
                 model.reload();
                 Display_DirectoryInfo(currentDir,root);
    }
    }//End homepage
    
    0 讨论(0)
  • 2020-12-08 22:21

    FINAL UPDATE: Found the problem and solved it: The following steps solve the problem,(but see the accepted answer for a better solution and a deep explanation of the problem):

    1. The implicit listeners registered are enough to do the job. No need to implement my own listener.
    2. When adding nodes and calling treeNodesInserted() it doesn't work (JTree not updated). But It works with calling treeStructureChanged().

    Apparently the implicit listeners are internally refreshing the tree the way i want, but only in their treeStructureChanged() method implementation. It would be good for JTree to provide this "algorithm" as a function in order to be able to be called manually.

    0 讨论(0)
  • 2020-12-08 22:24

    Your TreeModel is supposed to fire TreeModelEvents when it changes, and the JTree observes your model though a TreeModelListener to refresh itself when your model changes.

    So if you implement the TreeModelListener support correctly, you do not need to observe the model and inform the JTree, as it already does so itself. From an MVC perspecive, the JTree is your View/Controller, and the TreeModel is your Model (or rather: model adapter), which is observable.

    You could try force the JTree to update its visual state by calling repaint(), but I would recommend not doing so as it's not guaranteed to work. When you're unsure of how to do a fine-granular notification to a TreeModelListener, use TreeModelListener.treeStructureChanged(..) to notify a 'whole model' update (warning: can cause selections and node expansion states to be lost).

    0 讨论(0)
提交回复
热议问题