有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从CellEditorListener获取编辑的TreeNode

早些时候,我问如何在树节点被重命名(here)时触发事件。我的问题得到了回答,但我遇到了另一个问题。我需要访问CellEditorListener的editingStopped事件中正在编辑的TreeNode。这是我必须执行的代码:

package com.gamecreator;

import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultTreeCellEditor;

public class CustomCellEditorListener implements CellEditorListener {
    public CustomCellEditorListener() {

    }

    public void editingCanceled(ChangeEvent e) {

    }

    public void editingStopped(ChangeEvent e) {
        DefaultTreeCellEditor editor = (DefaultTreeCellEditor) e.getSource(); //This gives me the error.
        CustomTreeNode node = //What do I put here???;
        node.getResource().setName((String) node.getUserObject());

        //For debugging
        System.out.println(node.getResource().getName());
    }
}

我得到这个错误:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.tree.DefaultTreeCellEditor$1 cannot be cast to javax.swing.tree.DefaultTreeCellEditor

编辑: 在另一次尝试中,我在CustomCellEditorListener中使用了此代码

public void editingStopped(ChangeEvent e) {
    TreePath path = ((CustomTreeCellEditor) e.getSource()).getLastPath();  //This gives me the error.
    CustomTreeNode node = (CustomTreeNode) path.getLastPathComponent();
    node.getResource().setName((String) node.getUserObject());

    //For debugging
    System.out.println(node.getResource().getName());
}

以及CustomTreeCeleditor中的此代码

public TreePath getLastPath() {
    return lastPath;
}

我也犯了同样的错误(我想我会的)。我所拥有的应该是有效的,所以剩下的唯一真正的问题是,“为什么我会出现错误,我怎样才能纠正它?”但是如果有人有更好的方法来完成这一点,我愿意倾听

编辑2: 我已经做了一个小例子,说明我正在努力实现的目标,可以在here中找到(这是一个Eclipse归档文件)


共 (2) 个答案

  1. # 1 楼答案

    我找到了一个非常简单的解决方案。重命名TreeNode后,它将成为树中唯一选定的节点。因此,我能够使用:

        CustomTreeNode node = (CustomTreeNode) tree.getLastSelectedPathComponent();
    
  2. # 2 楼答案

    似乎您想在DefaultMutableTreeNode中编辑Resource的名称。正如您所发现的,ChangeEvent发送到editingStopped()in而不是aDefaultTreeCellEditor的来源;它是编辑器的(匿名)UI委托

    相反,在DefaultTreeCellEditor中重写getCellEditorValue(),如下所示。DefaultTreeCellRenderer只是通过^{}调用toString(),后者访问DefaultMutableTreeNode的用户对象

    附录:注意isCellEditable()确保只有叶节点可以编辑

    正如@kleopatra在评论中指出的那样,之前的TreeCellEditor实现是无效的,因为它修改了正在编辑的节点。下面的修订版本创建了一个具有更新名称的新节点;在这方面copy constructor将是有用的。优点是userObject仍然是Resource。另见本alternative approach

    image

    /**
     * @see https://stackoverflow.com/a/12651990/230513
     * @see https://stackoverflow.com/a/11639595/230513
     * @see https://stackoverflow.com/a/11113648/230513
     */
    public class TreeEditDemo extends JPanel {
    
        private JTree tree;
        private DefaultMutableTreeNode root;
        private DefaultTreeCellEditor editor;
        private JLabel label = new JLabel(" ", JLabel.CENTER);
    
        public TreeEditDemo() {
            super(new BorderLayout());
            root = new DefaultMutableTreeNode("Nodes");
            root.add(new DefaultMutableTreeNode(new Resource("one")));
            root.add(new DefaultMutableTreeNode(new Resource("two")));
            root.add(new DefaultMutableTreeNode(new Resource("three")));
            final DefaultTreeModel treeModel = new DefaultTreeModel(root);
            tree = new JTree(treeModel);
            tree.setEditable(true);
            editor = new MyTreeCellEditor(tree,
                (DefaultTreeCellRenderer) tree.getCellRenderer());
            tree.setCellEditor(editor);
            tree.getInputMap().put(
                KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "startEditing");
            this.add(new JScrollPane(tree));
            this.add(label, BorderLayout.SOUTH);
            tree.addTreeSelectionListener(new TreeSelectionListener() {
    
                @Override
                public void valueChanged(TreeSelectionEvent e) {
                    TreePath path = e.getNewLeadSelectionPath();
                    if (path != null) {
                        DefaultMutableTreeNode node =
                            (DefaultMutableTreeNode) path.getLastPathComponent();
                        if (node.isLeaf()) {
                            Resource user = (Resource) node.getUserObject();
                            label.setText(user.toString());
                        } else {
                            label.setText(" ");
                        }
                    }
                }
            });
            editor.addCellEditorListener(new CellEditorListener() {
    
                @Override
                public void editingStopped(ChangeEvent e) {
                    label.setText(editor.getCellEditorValue().toString());
                }
    
                @Override
                public void editingCanceled(ChangeEvent e) {
                }
            });
        }
    
        private static class MyTreeCellEditor extends DefaultTreeCellEditor {
    
            public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
                super(tree, renderer);
            }
    
            @Override
            public Object getCellEditorValue() {
                String value = (String) super.getCellEditorValue();
                return new Resource(value);
            }
    
            @Override
            public boolean isCellEditable(EventObject e) {
                return super.isCellEditable(e)
                    && ((TreeNode) lastPath.getLastPathComponent()).isLeaf();
            }
        }
    
        private static class Resource {
    
            String name;
    
            public Resource(String name) {
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            @Override
            public String toString() {
                return getName();
            }
        }
    
        private void display() {
            JFrame f = new JFrame("TreeEditorDemo");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(this);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new TreeEditDemo().display();
                }
            });
        }
    }