【问题标题】:JDialog - Refresh dynamically added nodes in JTreeJDialog - 刷新 JTree 中动态添加的节点
【发布时间】:2012-10-04 07:04:58
【问题描述】:

我在用于 JDialog 的 JTree 节点可见性方面存在问题。 当我想向模型中添加新节点时,Jtree 不会刷新。

奇怪的是,如果我设置了 setRootVisible(true),节点会按照它们应该的方式更新。

这里是代码。提前致谢

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class TestClass {

JTree tree;
DefaultTreeModel dm;
JDialog dialog;

public TestClass(){
    JFrame frame = new JFrame("title");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    JPanel showPane = new JPanel();
    showPane.setLayout(new BorderLayout()); 

    dm = new DefaultTreeModel(new DefaultMutableTreeNode("root"));
    tree = new JTree(dm);
    tree.setRootVisible(false);

    JButton button = new JButton("add node");
    button.addActionListener(new ActionListener(){

        public void actionPerformed(ActionEvent arg0) {
            DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();           
            dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount());

            int c = root.getChildCount();
            System.out.println("child count: " + c);

            for(int i=0; i<c; i++){
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i);
                System.out.println("has node:" + node.getUserObject().toString());
            }
        }

    });

    showPane.add(tree, BorderLayout.CENTER);
    showPane.add(button, BorderLayout.PAGE_END);

    JComponent[] inputComponents = new JComponent[] {showPane};

    Object[] opButtons = {"OK"};

    JOptionPane optPane = new JOptionPane(inputComponents       
            , JOptionPane.PLAIN_MESSAGE             
            , JOptionPane.CLOSED_OPTION             
            , null                                      
            , opButtons                             
            , opButtons[0]);                            

    optPane.setPreferredSize(new Dimension(400 ,250));

    dialog = optPane.createDialog(null, "Create new Application Node");
    dialog.setLocationRelativeTo(frame);
    dialog.setVisible(true);

    if(optPane.getValue() != null){
        System.exit(0);
    }

}

public static void main(String arg[]){
    TestClass myClass = new TestClass();
}

}

【问题讨论】:

  • 有两个因素结合起来隐藏添加的节点。 1)根不是不可见的。 2) 模型更新后节点不展开。

标签: java swing jtree jdialog treemodel


【解决方案1】:

每次添加新的子节点时,请确保扩展从新节点的父节点到根节点的路径:

DefaultMutableTreeNode newChild = new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1));
dm.insertNodeInto(newChild, root, root.getChildCount());
tree.expandPath(new TreePath(dm.getPathToRoot(newChild.getParent())));

【讨论】:

  • 是的,这就像魅力一样,虽然它仍然让我感到困惑。我不必为 JFrame 执行此操作。谢谢。
  • @user1503578 通常情况下,JTree 的根节点是展开的,但是在创建树时,根节点没有任何子节点,因此无法展开。请注意,即使根节点不可见,其展开状态仍控制其子节点的可见性。稍后当您添加新节点时,它们不会显示,因为根已折叠。
  • @GeoffReedy 基本正确,但挑剔我会认为 cannot - 这是模型的实现细节 :-)
【解决方案2】:

请同时检查另一个解决方案:

   DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); 
   model.reload(); 

API 说:

如果你修改了这个树节点,则调用 reload 方法 型号取决于。该模型将通知其所有侦听器 型号变了。

如需快速验证,请尝试以下操作:

public void actionPerformed(ActionEvent arg0) {
   DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
   dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount());

   int c = root.getChildCount();
   System.out.println("child count: " + c);

   DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); // !!!
   model.reload();   // !!!

   for (int i = 0; i < c; i++) {
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i);
       System.out.println("has node:" + node.getUserObject().toString());
   }
}

详情请看以下回答:

【讨论】:

  • 不要对简单的更改使用重新加载,而是确保模型适当通知(defaultTreeModel 将在 insertNodeInto 上)
【解决方案3】:

@JBNizet 的答案是正确的,总结一下:

  • 插入节点不会自动影响父节点的展开状态
  • 为了确保新插入的子节点可见,必须展开其父节点

添加一些替代 api 以使孩子可见:

dm.makeVisible(new TreePath(newChild.getPath());

关于@Geoff Reedy 的评论(我加粗):

JTree 的根节点通常是展开的,但是在创建树时,根节点没有任何子节点,因此它无法展开

cannot 并没有那么严格:它是否可以扩展(即使有零个孩子)实际上取决于模型的 isLeaf 的实现。可以说,根永远不会是叶子(即使没有孩子),因为它的本质是不是 :-) 可以通过

final DefaultTreeModel model = new DefaultTreeModel(root) {

    @Override
    public boolean isLeaf(Object node) {
        if (isRoot(node)) {
            return false;
        }
        return super.isLeaf(node);
    }

    private boolean isRoot(Object node) {
        return node != null && node == getRoot();
    }

};

使用这样的实现,根总是展开(根可见或不可见),并且新插入的直接子将显示出来,而不会使它们显式可见。

【讨论】:

    猜你喜欢
    • 2017-05-05
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多