从CellEditorListener被编辑树节点从CellEditorListener被编辑树节点

2019-06-02 13:16发布

早些时候,我问怎么当一个TreeNode改名(触发事件在这里 )。 我的问题得到回答,但我遇到了另一个问题。 我需要访问在CellEditorListener的editingStopped事件正在编辑的树节点。 这是我必须做这样的代码:

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

我得到这个错误:

异常的线程 “AWT-EventQueue的-0” java.lang.ClassCastException:javax.swing.tree.DefaultTreeCellEditor中的$ 1不能转换为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());
}

这个代码在CustomTreeCellEditor

public TreePath getLastPath() {
    return lastPath;
}

我得到了同样的错误(我希望我会)。 我有什么应该工作,所以剩下的唯一真正的问题是,“为什么我得到的错误,我怎么能解决这个问题?”但如果任何人有更好的方式来做到这一点,我愿意听。

编辑2:我已经做了什么,我试图完成,可以发现一个小例子在这里 (这是一个Eclipse存档)。

Answer 1:

看来,要编辑的名称ResourceDefaultMutableTreeNode 。 正如您看到的,在源ChangeEvent发送到editingStopped() DefaultTreeCellEditor ; 这是编辑的(匿名)UI委托。

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

附加物:注意isCellEditable()保证了只有叶节点可以被编辑。

正如评论@kleopatra笔记,以前TreeCellEditor执行是无效的,因为它修改正在编辑的节点。 下面的修订版创建具有更新的名称的新节点; 一个拷贝构造函数是在这方面非常有用。 其优点是, userObject仍然是一个Resource 。 另见本的替代方法 。

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


Answer 2:

我发现了一个解决方案,其实很简单。 当一个树节点被重命名,它最终被在树中只有选定的节点。 正因为如此,我才得以使用:

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


文章来源: Get Edited TreeNode from a CellEditorListener