如何手动选择JTree中的节点[嵌套节点的问题]

时间:2014-10-24 10:25:53

标签: java swing jtree treenode

我手动(通过我的java代码)选择JTree中的项目时遇到问题。我确实谷歌问题,并在这里和这里找到解决方案:

Java: How to programmatically select and expand multiple nodes in a JTree?

http://www.coderanch.com/t/543214/GUI/java/Select-node-Jtree

这段代码只对我有用。一旦我尝试选择更深层次的嵌套节点,我遇到了问题。由于我的生产代码非常杂乱,我构建了一个示例并在其中重现了我的确切问题。

DummyView.java

package de.fortis.tcws.client.controller;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

public class DummyView extends JFrame {

    private static final long serialVersionUID = 7301762327073611779L;

    private static final String ROOT_NAME = "Root";

    public JTree tree;
    public DefaultTreeModel model;
    public JPanel right;

    public DummyView() {
        super();
        initGui();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void initGui() {
        setSize(1600, 800);

        tree = new JTree();
        tree.setEditable(false);
        tree.addTreeSelectionListener(new DumSelectionListener());
        tree.addTreeExpansionListener(new DumExpansionListener());
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(ROOT_NAME);
        tree.setModel(model = new DefaultTreeModel(root, true));
        refreshNode(root);
        tree.setPreferredSize(new Dimension(200, 800));
        getContentPane().add(new JScrollPane(tree), BorderLayout.WEST);

        JScrollPane rightPan = new JScrollPane(right = new JPanel());
        right.add(new JLabel("Empty"));
        getContentPane().add(rightPan, BorderLayout.CENTER);
    }

    public void manualSelect(Object[] path) {
        DefaultMutableTreeNode target = (DefaultMutableTreeNode) tree.getModel().getRoot();
        for (Object uo : path) {
            refreshNode(target);
            target = getNodeByUserObject(target, uo);
        }

        navigateToNode(target);
    }

    public void navigateToNode(DefaultMutableTreeNode node) {
        TreeNode[] nodes = model.getPathToRoot(node);
        TreePath tpath = new TreePath(nodes);
        tree.scrollPathToVisible(tpath);
        tree.setSelectionPath(tpath);
    }

    public DefaultMutableTreeNode getNodeByUserObject(DefaultMutableTreeNode node, Object o) {
        for (int i = 0; i < node.getChildCount(); i++) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
            if (child.getUserObject().equals(o)) {
                return child;
            }
        }
        return null;
    }

    private class DumSelectionListener implements TreeSelectionListener {

        @Override
        public void valueChanged(TreeSelectionEvent e) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                e.getNewLeadSelectionPath().getLastPathComponent();
            right.removeAll();
            right.add(new JLabel("Node: " + node.getUserObject().toString()));
            right.revalidate();
            right.repaint();
        }
    }

    private class DumExpansionListener implements TreeExpansionListener {

        @Override
        public void treeExpanded(TreeExpansionEvent event) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
            refreshNode(node);
        }

        @Override
        public void treeCollapsed(TreeExpansionEvent event) {
        }
    }

    private void refreshNode(DefaultMutableTreeNode node) {
        node.removeAllChildren();
        Object uo = node.getUserObject();
        if (uo.equals(ROOT_NAME)) {
            for (int i = 1; i <= 10; i++) {
                DefaultMutableTreeNode n = new DefaultMutableTreeNode(new Integer(i));
                node.add(n);
            }
        } else if (uo instanceof Integer) {
            int num = (Integer) uo;
            for (int i = 1; i <= 9; i++) {
                DefaultMutableTreeNode n = new DefaultMutableTreeNode("" + num + "." + i);
                node.add(n);
            }
        } else {
            String uos = (String) uo;
            String[] split = uos.split("[.]");
            if (split.length == 2) {
                for (String let : new String[] {
                    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J"
                }) {
                    DefaultMutableTreeNode n = new DefaultMutableTreeNode(let);
                    node.add(n);
                }
            } else {
                String value = uos;
                DefaultMutableTreeNode parSplit = (DefaultMutableTreeNode) node.getParent();
                value = parSplit + value;
                DefaultMutableTreeNode parNum = (DefaultMutableTreeNode) parSplit.getParent();
                value = parNum + value;
                DefaultMutableTreeNode parRoot = (DefaultMutableTreeNode) parNum.getParent();
                value = parRoot + value;
                value = mdfive(value);

                DefaultMutableTreeNode n = new DefaultMutableTreeNode(value);
                node.add(n);
            }
        }
        model.nodeStructureChanged(node);
    }

    private String mdfive(String in) {
        String out = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(in.getBytes());
            byte[] bytes = md.digest();
            for (int i = 0; i < bytes.length; i++) {
                out += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return out.substring(0, 10);
    }
}

DummyTreeStarter.java

package de.fortis.tcws.client.controller;

public class DummyTreeStarter {

    public static void main(String[] args) {
        DummyView v = new DummyView();
        v.setVisible(true);
        v.manualSelect(new Object[] {
            //                          // execute this row to select root node
            //1                         // execute this row to select node '1'
            //1, "1.1"                  // execute this row to select node '1.1' - selected but not marked
            //1, "1.1", "A"             // execute this row to select node 'A' - exception
        });
    }
}

重要的方法是'manualSelect(String [])'。 它通过比较用户对象来遍历树,并找到目标节点。然后它调用'navigateToNode()',它使用上面链接中讨论的解决方案。

此方法表现不一致:

  • 如果使用空数组调用它,它将正确选择根节点。右侧窗格显示所选节点的文本。 =正确
  • 如果使用目标节点1调用它,它将正确选择节点1.右侧窗格显示所选节点的文本。 =正确
  • 如果您使用目标节点1.1调用它,它将选择节点1.1但由于某种原因它不会显示为标记(无背景)。右侧窗格显示所选节点的文本。 =只是部分正确
  • 如果使用目标节点A调用它,它将遇到异常。调试显示选择最初是相关的。您还可以观察右侧窗格,其中显示已选择“A”。但之后发生另一个TreeSelectionEvent,其NewLeadSelectionPath为null。我不知道第二个SelectionEvent是从哪里触发的。

我做错了吗?有没有人想解决这个问题?

此代码使用Java 1.6.0_39运行,这也是我将要在生产中使用的代码。

问候, 奥莱

编辑:拼写

1 个答案:

答案 0 :(得分:0)

当选择节点时,树正在刷新...... 删除这两行,它的工作原理:

@Override
public void treeExpanded(TreeExpansionEvent event) {
   //DefaultMutableTreeNode node = (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
   //refreshNode(node);
}