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
Get Edited TreeNode from a CellEditorListener
提问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 被重命名时如何触发事件(这里)。我的问题得到了回答,但我遇到了另一个问题。我需要访问在 CellEditorListener 的 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 Resource
in a DefaultMutableTreeNode
. As you've found, the source of the ChangeEvent
sent 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 DefaultTreeCellRenderer
simply 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 TreeCellEditor
implementation 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 userObject
remains a Resource
. See also this alternative approach.
正如@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();
}
});
}
}