早些时候,我问怎么当一个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存档)。
看来,要编辑的名称Resource
在DefaultMutableTreeNode
。 正如您看到的,在源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();
}
});
}
}
我发现了一个解决方案,其实很简单。 当一个树节点被重命名,它最终被在树中只有选定的节点。 正因为如此,我才得以使用:
CustomTreeNode node = (CustomTreeNode) tree.getLastSelectedPathComponent();