I\'ve created a tree cell renderer/editor framework that is admittedly a little bit hacky, but it works perfectly on Windows and Linux. The image below illustrates a sample set
I'm not sure I understand the requirement, but the example below adds a convenient key binding and works with either single-click approach shown here. I've chosen to override canEditImmediately()
, as suggested by kleopatra, subject to her caveats concerning usability.
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.util.EventObject;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
/**
* @see https://stackoverflow.com/a/15738813/230513
* @see https://stackoverflow.com/q/15625424/230513
*/
public class Test {
private static Icon one;
private static Icon two;
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTree tree = new JTree();
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
final TreeRenderer renderer = new TreeRenderer();
tree.setCellRenderer(renderer);
tree.setCellEditor(new TreeEditor(tree, renderer));
tree.setEditable(true);
tree.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "startEditing");
f.add(new JScrollPane(tree));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static class TreeRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
String s = node.getUserObject().toString();
if ("colors".equals(s)) {
setOpenIcon(one);
setClosedIcon(one);
} else if ("sports".equals(s)) {
setOpenIcon(two);
setClosedIcon(two);
} else {
setOpenIcon(getDefaultOpenIcon());
setClosedIcon(getDefaultClosedIcon());
}
super.getTreeCellRendererComponent(
tree, value, sel, exp, leaf, row, hasFocus);
return this;
}
}
private static class TreeEditor extends DefaultTreeCellEditor {
public TreeEditor(JTree tree, DefaultTreeCellRenderer renderer) {
super(tree, renderer);
}
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean isSelected, boolean exp, boolean leaf, int row) {
Component c = super.getTreeCellEditorComponent(
tree, value, isSelected, exp, leaf, row);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
String s = node.getUserObject().toString();
if ("colors".equals(s)) {
editingIcon = one;
} else if ("sports".equals(s)) {
editingIcon = two;
}
return c;
}
@Override
protected boolean canEditImmediately(EventObject event) {
if ((event instanceof MouseEvent)
&& SwingUtilities.isLeftMouseButton((MouseEvent) event)) {
MouseEvent me = (MouseEvent) event;
return ((me.getClickCount() >= 1)
&& inHitRegion(me.getX(), me.getY()));
}
return (event == null);
}
}
public static void main(String[] args) throws Exception {
one = new ImageIcon(ImageIO.read(
new URL("http://i.imgur.com/HtHJkfI.png")));
two = new ImageIcon(ImageIO.read(
new URL("http://i.imgur.com/w5jAp5c.png")));
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Test().display();
}
});
}
}