But I can not set custom open/close
Having run you code, it would appear that the images you are trying to load are "meant" to be embedded within you application (that is, they don't reside some where on the disk out side of the application context).
So instead of doing this...
CustomTreeNode root = new CustomTreeNode(new ImageIcon("images/Circle_3.gif"), bigBoss);
Try doing something like this...
CustomTreeNode root = new CustomTreeNode(new ImageIcon(ImageIO.read(getClass().getResource("/images/Circle_3.gif"))), bigBoss);
Instead. This will cause Java to look within it's class path (including any JAR resources) to find the images.
When I run you code without this fix, nothing worked, when I updated it to use this feature, it worked fine.
NB: ImageIO#read
throws an IOException
so look out for it
Updated
After much head scratching...I changed the cell renderer to look like this...
class CustomeTreeCellRenderer extends DefaultTreeCellRenderer {
public CustomeTreeCellRenderer() {
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
// if (!leaf) {
CustomTreeNode node = (CustomTreeNode) value;
if (node.getIcon() != null) {
System.out.println(node + " - " + node.getIcon());
setClosedIcon(node.getIcon());
setOpenIcon(node.getIcon());
setLeafIcon(node.getIcon());
} else {
System.out.println(node + " - default");
setClosedIcon(getDefaultClosedIcon());
setLeafIcon(getDefaultLeafIcon());
setOpenIcon(getDefaultOpenIcon());
}
// }
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
return this;
}
}
It it cleared it all up...
Calling setXxxIcon
doesn't effect the current renderer, but the future renderer. That is. If you call setOpenIcon
AFTER you've already called super.getTreeCellRendererComponent
, it will not effect the current renderer, but it will effect the next call to super.getTreeCellRendererComponent
as the set method is simply setting the value of class variable.
Additional
Trashgod has made a valuable comment about relying on the implementation and the way it works now.
Instead of calling DefaultTreeCellRenderer#setXxxIcon
within the getTreeCellRendererComponent
method, you should actually simply call DefaultTreeCellRenderer#setIcon
, using the required icon based on the parameters passed to it.
This means you can call super.getTreeCellRendererComponent
first and then override the behavior of the icons after it.
You could also grab a reference to Object
value and override the DefaultTreeCellRenderer#getXxxIcon
methods and based on the value, change the return values of these methods. I personally, wouldn't courage this as it changes the documented behavior of the renderer
In your TreeCellRenderer
, you can use setOpenIcon()
and setClosedIcon()
as required in conjunction with the defined parameters and predicates related to your model. Given a tree having the default JTree
model, the TreeRenderer
below will use the closed
and open
icons for the sports
node:
private static class TreeRenderer extends DefaultTreeCellRenderer {
private static final Icon closed =
(Icon) UIManager.get("InternalFrame.maximizeIcon");
private static final Icon open =
(Icon) UIManager.get("InternalFrame.minimizeIcon");
@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 ("sports".equals(s)) {
setOpenIcon(open);
setClosedIcon(closed);
} else {
setOpenIcon(getDefaultOpenIcon());
setClosedIcon(getDefaultClosedIcon());
}
super.getTreeCellRendererComponent(
tree, value, sel, exp, leaf, row, hasFocus);
return this;
}
}
See also this related example.