I have a JTree with a custom TreeModel and a custom TreeRenderer. The Tree Model contains a bunch of objects of different types. One of these types is displayed differently than the others: The displayed text is a concatenation of two fields of the object. When i edit the cell, I want to update one of these fields with the edited text. So far i got it working pretty well.
My Problem: It is confusing when the text, which is displayed while editing, is the complete concatenated value of 2 fields, even though you're in fact just editing one of the fields. So i want to display only the content of the one field you're editing when the user starts editing.
I tried to do this with a custom CellEditor, and I saw the way it's supposed to work and the approach seems overkill in my case. I just want to alter the displayed text in one of many cases, so naturally I want to implement that, and not a whole CellEditor for the entire content of my Tree.
Is there a faster and easier way to do this, or do I have to use a custom editor?
Thanks
The JTree class is used to display the tree structured data or hierarchical data. JTree is a complex component. It has a 'root node' at the top most which is a parent for all nodes in the tree. It inherits JComponent class.
JTree is a Swing component with which we can display hierarchical data. JTree is quite a complex component. A JTree has a 'root node' which is the top-most parent for all nodes in the tree. A node is an item in a tree. A node can have many children nodes.
There is no way around a custom editor and it is the shortest solution possible :-) Additionally, you'll need some means in the data realm that can interpret the editing value as appropriate and update itself, f.i. a custom node.
F.i (will comment it later, my lame firefox on this machine is driving me up the walls)
/**
* 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();
}
});
}
}
A custom editor is required. MyTreeCellEditor
, illustrated here, shows one approach. It updates an arbitrary attribute of a userObject
, which is named Resource
and held in a DefaultMutableTreeNode
. As the attribute is text, it also uses the DefaultTreeCellRenderer
. Your custom TreeModel
probably manages a similar userObject
that is the parent of your "objects of different types."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With