User123 User123 - 7 months ago 38
Java Question

How to set Jtree node icon dynamically

I want to display separate icon for grouped and ungrouped nodes.I created a customTreeCellRender.My sample codes given below.In for loop odd one nodes have one icon and evens have another.But not change the icon of nodes.In my application ,populating tree nodes from db and grouping based on some conditions.This is a sample runnable code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;

public class TestTree extends JDialog {

JTree tree;

DefaultTreeModel treeModel;

public TestTree() {
setSize(300, 800);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
System.out.println(getContentPane().getBackground());
}

protected static ImageIcon createImageIcon(String path) throws MalformedURLException {
java.net.URL imgURL = new URL(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}

public void init() throws MalformedURLException {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Numbers");
treeModel = new DefaultTreeModel(root);
tree = new JTree(treeModel);
tree.setBackground(new Color(238, 238, 244));
tree.setOpaque(true);

CustomIconRenderer customIconRenderer = new CustomIconRenderer(true);
customIconRenderer.setTextSelectionColor(Color.white);
customIconRenderer.setBackgroundSelectionColor(Color.blue);
customIconRenderer.setBorderSelectionColor(Color.black);
customIconRenderer.setBackgroundNonSelectionColor(new Color(238, 238,
244));
ImageIcon icon = createImageIcon("http://i.stack.imgur.com/wCF8S.png");
customIconRenderer.setLeafIcon(icon);


for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
DefaultMutableTreeNode subroot = new DefaultMutableTreeNode(
"node_" + i);
root.add(subroot);

tree.setCellRenderer(new CustomIconRenderer(false));

if (i % 3 == 0) {
for (int j = 10; j < 15; j++) {
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(
"node_" + j);
subroot.add(leaf);
}
}

} else {
DefaultMutableTreeNode subroot = new DefaultMutableTreeNode(
"node_" + i);
root.add(subroot);
tree.setCellRenderer(new CustomIconRenderer(true));
if (i % 4 == 0) {
for (int j = 15; j < 20; j++) {
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(
"node_" + j);
subroot.add(leaf);
}

}

}
}

for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}

tree.setCellRenderer(customIconRenderer);

getContentPane().add(tree, BorderLayout.CENTER);
}

public static void main(String args[]) throws MalformedURLException {
TestTree tt = new TestTree();
tt.init();
tt.setVisible(true);
}
}
class CustomIconRenderer extends DefaultTreeCellRenderer {
/**
*
*/
private static final long serialVersionUID = 967937360839244309L;
ImageIcon groupedIcon;
ImageIcon unGroupedIcon;
boolean grouped;

public CustomIconRenderer() {

}

public CustomIconRenderer(boolean grouped) throws MalformedURLException {
this.grouped = grouped;
URL url=new URL("http://i.stack.imgur.com/wCF8S.png");
URL url1=new URL("http://i.stack.imgur.com/T5uTa.png");
groupedIcon = new ImageIcon(url1
);
unGroupedIcon = new ImageIcon(url
);
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {

super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
row, hasFocus);

Object nodeObj = ((DefaultMutableTreeNode) value).getUserObject();
// check whatever you need to on the node user object
if (grouped) {
setIcon(unGroupedIcon);
} else {
System.out.println("reached");
setIcon(groupedIcon);
}
return this;
}
}

Answer

There were a couple of mistakes in the original code, most notably:

  • Setting a cell renderer every time a node was added (a tree can only have a single cell renderer, so the 'last one added' wins).
  • Expecting that the slightly altered method you coded for getting a tree cell renderer would ever be called. (You did do that experiment I proposed in comment, right?)

I think this is more along the lines of the requirement. Note that I was trying to stick as close to the original code as possible. I would approach this differently to how it is seen here.

  • This example: Examines the String value of the value passed to the method to get the cell renderer to see if it contains an _ character, then splits the string and parses the last part back to an integer value.
  • How it should be done: Pass Integer objects for the leaves of the tree. In the cell renderer check of the value is an instance of Integer and if so, prefix the number with node_ ..

enter image description here

import java.awt.*;
import java.net.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TestTree extends JDialog {

    JTree tree;

    DefaultTreeModel treeModel;

    public TestTree() {
        setSize(300, 800);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        System.out.println(getContentPane().getBackground());
    }

    protected static ImageIcon createImageIcon(String path) throws MalformedURLException {
        java.net.URL imgURL = new URL(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    public void init() throws MalformedURLException {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Numbers");
        treeModel = new DefaultTreeModel(root);
        tree = new JTree(treeModel);
        tree.setBackground(new Color(238, 238, 244));
        tree.setOpaque(true);

        CustomIconRenderer customIconRenderer = new CustomIconRenderer();
        customIconRenderer.setTextSelectionColor(Color.white);
        customIconRenderer.setBackgroundSelectionColor(Color.blue);
        customIconRenderer.setBorderSelectionColor(Color.black);
        customIconRenderer.setBackgroundNonSelectionColor(new Color(238, 238,
                244));
        ImageIcon icon = createImageIcon("http://i.stack.imgur.com/wCF8S.png");
        customIconRenderer.setLeafIcon(icon);
        tree.setCellRenderer(new CustomIconRenderer());

        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                DefaultMutableTreeNode subroot = new DefaultMutableTreeNode(
                        "node_" + i);
                root.add(subroot);

                if (i % 3 == 0) {
                    for (int j = 10; j < 15; j++) {
                        DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(
                                "node_" + j);
                        subroot.add(leaf);
                    }
                }
            } else {
                DefaultMutableTreeNode subroot = new DefaultMutableTreeNode(
                        "node_" + i);
                root.add(subroot);
                if (i % 4 == 0) {
                    for (int j = 15; j < 20; j++) {
                        DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(
                                "node_" + j);
                        subroot.add(leaf);
                    }
                }
            }
        }

        for (int i = 0; i < tree.getRowCount(); i++) {
            tree.expandRow(i);
        }

        tree.setCellRenderer(customIconRenderer);

        getContentPane().add(tree, BorderLayout.CENTER);
    }

    public static void main(String args[]) throws MalformedURLException {
        TestTree tt = new TestTree();
        tt.init();
        tt.setVisible(true);
    }
}

class CustomIconRenderer extends DefaultTreeCellRenderer {

    /**
     *
     */
    private static final long serialVersionUID = 967937360839244309L;
    ImageIcon groupedIcon;
    ImageIcon unGroupedIcon;

    public CustomIconRenderer() throws MalformedURLException {
        URL url = new URL("http://i.stack.imgur.com/wCF8S.png");
        URL url1 = new URL("http://i.stack.imgur.com/T5uTa.png");
        groupedIcon = new ImageIcon(url1);
        unGroupedIcon = new ImageIcon(url);
    }

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value,
            boolean sel, boolean expanded, boolean leaf, int row,
            boolean hasFocus) {

        super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
                row, hasFocus);

        Object nodeObj = ((DefaultMutableTreeNode) value).getUserObject();
        String s = nodeObj.toString();
        System.out.println("s: " + s);
        boolean includesUnderscore = s.indexOf("_") > 0;
        if (includesUnderscore) {
            String lastPart = s.split("_")[1];
            int num = Integer.parseInt(lastPart);
            // check whatever you need to on the node user object
            if (num % 2 == 0) {
                setIcon(unGroupedIcon);
            } else {
                System.out.println("reached");
                setIcon(groupedIcon);
            }
        }
        return this;
    }
}