JTree更新节点而不会崩溃

Kai*_*ugo 12 java swing jtree defaulttablemodel

我有一个需要JTree更新节点的Java SE 7应用程序.从使用此线程的Oracle提供的教程中,没有给出关于如何在代码上更新标签(树上节点的显示文本)的提示.目前我DefaultTreeModel用作我的模型JTreeDefaultMutableTreeNode所述树的节点.

为了进一步详细说明我正在处理的应用程序,我正在开发一个聊天工具,其中显示的联系人每个帐户的可用性状态(无论是在线,离线等).

问题是,如何更新特定节点的显示文本,而不是(最多)将其从父节点中删除,并将其添加到指定的索引上.喜欢DefaultMutableTreeNode.setText("<new label>")


更新:2013年1月20日

重新定义问题以便澄清.

Lee*_*dor 9

也许如果您使用'nodeChanged()'而不是'reload()',您将获得所需的效果.

DefaultTreeModel类上有许多方法可以更改和重绘树的各个部分.DefaultTreeModel上还有其他方法只会导致重绘.

您提到'重新加载(节点)'并注释它会在您调用树时导致树崩溃.'reload'导致从该节点开始完全重绘整个子树.(但如果该节点不可见,则不会改变任何内容.)这称为"结构更改".

'insertNodeInto()'和'removeNodeFromParent()'通过添加或删除节点然后重绘来修改树结构.

我认为'nodeChanged()'是你需要的,因为它只是通知模型节点中发生了某些变化,导致它以不同的方式显示.也许可显示的文本现在不同于它.也许您更改了节点中的用户对象.那是在节点上调用'nodeChanged()'的时候.

您应该尝试使用'nodeChanged()'代替您自己的代码中的'reload()'调用,该代码正在折叠,并且在提供的示例程序vels4j中.这可能会解决问题.

请注意,DefaultTreeModel上还有另外两个方法系列,在其他情况下使用:

这些方法与树节点一起使用,并使用树路径来定义更改发生的位置.它们不会更改树下的数据结构,但会通知模型更改了某些内容,以便它可以通知侦听器实际重绘内容或以其他方式响应更改.

nodesWereInserted() nodesWereRemovde() nodesChanged() nodeStructureChanged()

还有一组fire...()在DefaultTreeModel内部使用的方法以及您可能创建的任何子类.他们只是通知任何听众改变了一些事情.请注意,它们受到保护.

  • 您可以使用@ vels4j代码并将reload()调用更改为nodeChanged().我认为不需要进一步的任何事情.我希望有一种方法可以分割信用,因为他/她完成了大部分工作,可以给你答案.我刚刚添加了一项改进,以防止崩溃并认为存在结构变化. (4认同)

vel*_*s4j 7

愿这个简单且可执行的程序帮助您解决问题.

public class JTreeDemo  extends JPanel
    implements Runnable {

private JTree tree;
private DefaultTreeModel treeModel ;
private Random rnd = new Random();
private List<User> userList;
public JTreeDemo() {
    super( );

    //Create the nodes.
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode("Users");
    treeModel = new DefaultTreeModel(top);
    createNodes(top);

    //Create a tree that allows one selection at a time.
    tree = new JTree(treeModel);
    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);
}

public String getRandomStatus() {
    int nextInt = rnd.nextInt(100);
    if( nextInt%2==0) {
        return "Online";
    } else {
        return "Offline";
    }
}
@Override
public void run() {
     while(true) {
        try {   
          Thread.sleep(1000);
          int nextInt = rnd.nextInt(10);
          User user = userList.get(nextInt);
          user.setStatus(getRandomStatus());
          treeModel.nodeChanged(user);
        } catch (InterruptedException ex) {
            // handle it if necessary
        }
     }
}

private class User extends DefaultMutableTreeNode {
    public String userName;
    public String status;

    public User(String name) {
        userName = name;

    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }

    @Override
    public String toString() {
        String color = status.equals("Online") ? "Green" : "Red";
        return "<html><b color='"+color+"'>"+
                userName +"-"+status +"</b></html>";
    }

}


private void createNodes(DefaultMutableTreeNode top) {
    userList = new ArrayList() ;
    for(int i=0;i<10;i++) {
        User u1 = new User("User " + (i+1));
        u1.setStatus("Online");
         top.add(u1);
         userList.add(u1);
    }
}

private static void createAndShowGUI() {

    JFrame frame = new JFrame("TreeDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Add content to the window.
    JTreeDemo jTreeDemo = new JTreeDemo();
    frame.add(jTreeDemo);
    frame.pack();
    frame.setVisible(true);
    // update status randomly
    Thread thread = new Thread(jTreeDemo);
    thread.start();
}

 public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
 }
}
Run Code Online (Sandbox Code Playgroud)

我已经添加了一个Thread来随机更新Status,希望你可以根据你的需要进行修改.

输出:
在此输入图像描述


编辑:
1.基于建议我删除reload(node)并添加了树模型重新加载.