java 从 CellEditorListener 获取编辑的 TreeNode

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11107984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:50:33  来源:igfitidea点击:

Get Edited TreeNode from a CellEditorListener

javaswingeventsrenametreenode

提问by jimn346

Earlier I asked how to fire an event when a TreeNode was renamed (here). My question was answered, but I ran into another problem. I need to access the TreeNode that is being edited in the CellEditorListener's editingStopped event. This is the code I have to do so:

早些时候我问过当 TreeNode 被重命名时如何触发事件(这里)。我的问题得到了回答,但我遇到了另一个问题。我需要访问在 Ce​​llEditorListener 的 editStopped 事件中正在编辑的 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());
    }
}

I get this error:

我收到此错误:

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

线程“AWT-EventQueue-0”中的异常 java.lang.ClassCastException:javax.swing.tree.DefaultTreeCellEditor$1 无法转换为 javax.swing.tree.DefaultTreeCellEditor

EDIT: In another attempt, I used this code in the CustomCellEditorListener

编辑:在另一次尝试中,我在 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());
}

and this code in the CustomTreeCellEditor

以及 CustomTreeCellEditor 中的这段代码

public TreePath getLastPath() {
    return lastPath;
}

I got the same error (I expected I would). What I have should work, so the only real question remaining is, "Why am I getting the error and how can I fix it?," but if anyone has a better way to accomplish this, I'm willing to listen.

我遇到了同样的错误(我希望我会)。我所拥有的应该可以工作,所以剩下的唯一真正的问题是,“为什么我会收到错误,我该如何解决它?”但如果有人有更好的方法来实现这一点,我愿意倾听。

EDIT 2: I have made a small example of what I'm trying to accomplish that can be found here(It's an Eclipse archive).

编辑 2:我做了一个小例子来说明我想要完成的事情,可以在这里找到(这是一个 Eclipse 存档)。

采纳答案by jimn346

I found a solution that was actually very simple. When a TreeNode is renamed, it ends up being the only selected node in the tree. Because of that, I was able to use:

我找到了一个实际上非常简单的解决方案。当 TreeNode 被重命名时,它最终成为树中唯一选定的节点。因此,我能够使用:

    CustomTreeNode node = (CustomTreeNode) tree.getLastSelectedPathComponent();

回答by trashgod

It appears that you want to edit the name of a Resourcein a DefaultMutableTreeNode. As you've found, the source of the ChangeEventsent to editingStopped()in nota DefaultTreeCellEditor; it is the editor's (anonymous) UI delegate.

看来您要编辑 aResource中的 a名称DefaultMutableTreeNode。正如您看到的,的源ChangeEvent发送到editingStopped()没有一个DefaultTreeCellEditor; 它是编辑器的(匿名)UI 委托。

Instead, override getCellEditorValue()in your DefaultTreeCellEditor, as shown below. The DefaultTreeCellRenderersimply calls toString(), via convertValueToText(), which accesses the user object of DefaultMutableTreeNode.

相反,覆盖getCellEditorValue()您的DefaultTreeCellEditor,如下所示。在DefaultTreeCellRenderer简单地调用toString(),通过convertValueToText(),它访问的用户对象DefaultMutableTreeNode

Addenda: Note that isCellEditable()ensures that only leaf nodes can be edited.

附录:请注意isCellEditable()确保只能编辑叶节点。

As @kleopatra notes in comments, the previous TreeCellEditorimplementation was invalid, as it modified the node being edited. The revised version below creates a new node having the updated name; a copy constructorwould be useful in this context. The advantage is that the userObjectremains a Resource. See also this alternative approach.

正如@kleopatra 在评论中指出的那样,之前的TreeCellEditor实现是无效的,因为它修改了正在编辑的节点。下面的修订版本创建了一个具有更新名称的新节点;一个拷贝构造函数是在这方面非常有用。优点是userObject保留了一个Resource. 另请参阅此替代方法

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();
            }
        });
    }
}