JTree: Set custom open/closed icons for individual groups

icons, java, jtree, swing, treecellrenderer

Solution

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.

Problem

- I know how to set custom leaf icons in JTree - I know how to set custom closed/open icons for all group nodes But I can not set custom open/closed icons based on the group node names, for example of node could be called Emails (so it is nice to have an envelop icon) or one group may be called tasks and so on. I tried to do this by overriding the `getTreeCellRendererComponent` method of class `DefaultTreeCellRenderer` But changing the `icon` for the current `node` will affect for the next node only! How to set custom open/closed icons for individual groups? Please take a look at my code: Employee.java ``` package com.ehsunbehravesh.swing; import java.util.Random; public class Employee { public String name; public int id; public boolean isBoss; public Employee[] employees; public Employee(String name, boolean isBoss) { this.name = name; this.isBoss = isBoss; this.id = new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE); } @Override public String toString() { return this.name; } static String randomName() { String chars = "abcdefghijklmnopqrstuvwxyz"; StringBuilder builder = new StringBuilder(); Random r = new Random(System.currentTimeMillis()); int length = r.nextInt(10) + 1; for (int i = 0; i < length; i++) { builder.append(chars.charAt(r.nextInt(chars.length()))); } return builder.toString(); } } ``` CustomTreeNode.java ``` package com.ehsunbehravesh.swing; import javax.swing.ImageIcon; import javax.swing.tree.DefaultMutableTreeNode; public class CustomTreeNode extends DefaultMutableTreeNode { /** * The icon which is displayed on the JTree object. open, close, leaf icon. */ private ImageIcon icon; public CustomTreeNode(ImageIcon icon) { this.icon = icon; } public CustomTreeNode(ImageIcon icon, Object userObject) { super(userObject); this.icon = icon; } public CustomTreeNode(ImageIcon icon, Object userObject, boolean allowsChildren) { super(userObject, allowsChildren); this.icon = icon; } public ImageIcon getIcon() { return icon; } public void setIcon(ImageIcon icon) { this.icon = icon; } } ``` CustomeTreeCellRenderer.java ``` package com.ehsunbehravesh.swing; import java.awt.Component; import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; class CustomeTreeCellRenderer extends DefaultTreeCellRenderer { public CustomeTreeCellRenderer() { } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, leaf, expanded, leaf, row, hasFocus); if (!leaf) { CustomTreeNode node = (CustomTreeNode) value; System.out.println(((Employee) node.getUserObject()).name); if (node.getIcon() != null) { System.out.println(node.getIcon().toString()); setClosedIcon(node.getIcon()); setOpenIcon(node.getIcon()); } else { setClosedIcon(getDefaultClosedIcon()); setClosedIcon(getDefaultOpenIcon()); setOpenIcon(getDefaultOpenIcon()); } } return this; } } ``` Test1.java ``` package com.ehsunbehravesh.swing; import java.awt.BorderLayout; import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTree; import javax.swing.tree.DefaultTreeModel; class TreeSample { public static void main(String args[]) { JFrame f = new JFrame("JTree Sample"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel pnlMain = new JPanel(new BorderLayout()); pnlMain.setBackground(Color.white); createTree(pnlMain); f.setContentPane(pnlMain); f.setSize(300, 200); f.setVisible(true); } private static void createTree(JPanel pnlMain) { Employee bigBoss = new Employee(Employee.randomName(), true); Employee[] level1 = new Employee[5]; bigBoss.employees = level1; for (int i = 0; i < level1.length; i++) { level1[i] = new Employee(Employee.randomName(), true); } for (int i = 0; i < level1.length; i++) { Employee employee = level1[i]; if (employee.isBoss) { int count = 5; employee.employees = new Employee[count]; for (int j = 0; j < employee.employees.length; j++) { employee.employees[j] = new Employee(Employee.randomName(), false); } } } CustomTreeNode root = new CustomTreeNode(new ImageIcon("images/Circle_3.gif"), bigBoss); DefaultTreeModel model = new DefaultTreeModel(root); for (Employee employee : bigBoss.employees) { CustomTreeNode boss = new CustomTreeNode(new ImageIcon("images/Circle_2.gif"), employee); root.add(boss); if (employee.isBoss) { for (Employee employee1 : employee.employees) { CustomTreeNode emp = new CustomTreeNode(new ImageIcon("images/Circle_1.gif"), employee1); boss.add(emp); } } } JTree tree = new JTree(model); tree.setCellRenderer(new CustomeTreeCellRenderer()); pnlMain.add(tree, BorderLayout.CENTER); } } ```

Original source

Related problems