我有一个带有自定义TreeModel和自定义TreeRenderer的JTree。树模型包含一堆不同类型的对象。 其中一种类型的显示方式与其他类型不同:显示的文本是对象的两个字段的串联。当我编辑单元格时,我想用编辑的文本更新其中一个字段。到目前为止,我的工作得很好。
我的问题:编辑时显示的文字是令人困惑的 2个字段的完整连接值,即使您实际上只是编辑其中一个字段。所以我想只显示用户开始编辑时正在编辑的一个字段的内容。
我尝试使用自定义CellEditor执行此操作,并且我看到了它应该工作的方式,并且这种方法在我的情况下似乎有些过分。我只是想在许多情况下改变显示的文本,所以我自然而然地希望实现它,而不是整个CellEditor来实现我的Tree的整个内容。
是否有更快更简单的方法,或者我是否必须使用自定义编辑器?
由于
答案 0 :(得分:9)
无法绕过自定义编辑器并且它是最短的解决方案:-)此外,您需要在数据域中使用某些方法来解释编辑值并更新本身,fi自定义节点。
F.i(稍后会发表评论,我这台机器上的蹩脚火狐正在把我推到墙上)
/**
* Basic code stolen from @trashgod at
* @see http://stackoverflow.com/a/11113648/230513
*/
public class TreeEditDemo extends JPanel {
private JTree tree;
private DefaultMutableTreeNode root;
private DefaultTreeCellEditor editor;
public TreeEditDemo() {
super.setLayout(new GridLayout());
root = new DefaultMutableTreeNode("Nodes");
root.add(new MyResourceNode(new Resource("one", "first")));
root.add(new MyResourceNode(new Resource("two", "first")));
tree = new JTree(root);
tree.setEditable(true);
editor = new MyTreeCellEditor(tree,
(DefaultTreeCellRenderer) tree.getCellRenderer());
tree.setCellEditor(editor);
this.add(new JScrollPane(tree));
}
private static class MyTreeCellEditor extends DefaultTreeCellEditor {
public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
super(tree, renderer);
}
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row) {
if (value instanceof MyResourceNode) {
value = ((MyResourceNode) value).getName();
}
return super.getTreeCellEditorComponent(tree, value, isSelected, expanded,
leaf, row);
}
@Override
public boolean isCellEditable(EventObject e) {
return super.isCellEditable(e)
&& ((TreeNode) lastPath.getLastPathComponent()).isLeaf();
}
}
public static class MyResourceNode extends DefaultMutableTreeNode {
/**
* @param resource
*/
public MyResourceNode(Resource resource) {
super(resource);
}
@Override
public void setUserObject(Object userObject) {
if (userObject instanceof String) {
setName((String) userObject);
} else if (userObject instanceof Resource) {
super.setUserObject(userObject);
}
}
public void setName(String name) {
if (getUserObject() != null) {
getUserObject().setName(name);
}
}
public String getName() {
if (getUserObject() != null) {
return getUserObject().getName();
}
return null;
}
@Override
public Resource getUserObject() {
return (Resource) super.getUserObject();
}
}
private static class Resource {
String name;
private String category;
public Resource(String name, String category) {
this.name = name;
this.category = category;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
// BEWARE: don't do this in production code!
return name + " (" + category + ")";
}
}
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();
}
});
}
}
答案 1 :(得分:3)
需要自定义编辑器。图示here的MyTreeCellEditor
显示了一种方法。它会更新userObject
的任意属性,该属性名为Resource
并保存在DefaultMutableTreeNode
中。由于属性是文本,因此它也使用DefaultTreeCellRenderer
。您的自定义TreeModel
可能会管理一个类似的userObject
,它是您“不同类型的对象”的父级。