javaswingjtreetreenodetreecellrenderer

Set icon to each node in Jtree


I want to set a different icon for each node in my JTree component. I'm loading each node from a database using a while loop. I set each icon like a root, leaf, or parent. I set them as follows:

All my declarations are global:

private ResultSet myResultSet;
protected DefaultTreeModel treeModel;
private DefaultMutableTreeNode rootNode,childNode,parent1,parent2;

This is how I set my nodes:

myResultSet=rtnNodes(); /*Method that returns a RS with my nodes*/
while(myResultSet.next()){
  switch(myResultSet.getInt(1)){  /*The first column is the type of node: root, parent, leaf...*/
    case 0: treeModel = new DefaultTreeModel((rootNode=new DefaultMutableTreeNode(myResultSet.getString(2)))); break;  /*root node*/
    case 1: case 4: parent1 = parent2 = makeNode(rootNode); break;  /*parent node*/
    case 2: makeNode(parent2); break;  /*leaf node*/
    case 3: parent2 = makeNode(parent1); break;  /*sub patern node*/
  } /*makeNode is the method where I create the nodes*/
}

The makeNode method is this:

public DefaultMutableTreeNode makeNode(DefaultMutableTreeNode parent){
  //The second column in the RS is the name of the node
  treeModel.insertNodeInto((childNode=new DefaultMutableTreeNode(myResultSet.getString(2))),parent,parent.getChildCount());
  return childNode;
}

After filling the treemodel with my nodes, I set the model to my JTree:

myJTree.setModel(treeModel);
myJTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

But the problem comes when I try to set the icons. I create a subclass called MyTreeRenderer, and I use this:

myJTree.setCellRenderer(new MyTreeRenderer());

But it doesn't set the icons as I want, the subclass is:

private ImageIcon root,parent,leaf;

public MyTreeRenderer() {
   root=setIcons(2);  /*setIcons is a method that I dont publish in this post, that helps me to set the path of the icons*/
   parent=setIcons(3);
   leaf=setIcons(4);
}

@Override
public Component getTreeCellRendererComponent(JTree tree,Object value,boolean selected,boolean expanded,boolean leaf,int row,boolean hasFocus){               
   super.getTreeCellRendererComponent(tree,value,selected,expanded,leaf,row,hasFocus);
   DefaultMutableTreeNode nodo = (DefaultMutableTreeNode)value;
   TreeNode t = nodo.getParent();
   if(t!=null){
      setIcon(root);
   }
   return this;
}

How can I set the icon for each node without using his name? The code of the subclass, as is, set all the nodes with the same icon, and each time I select a node in the jtree, the getTreeCellRendererComponent runs, I don´t want this.


Solution

  • You can change default UI values for icons of JTree nodes without any custom renderer:

    URL resource = logaff.class.getResource(IMAGE);
    Icon icon = new ImageIcon(resource);
    
    UIManager.put("Tree.closedIcon", icon);
    UIManager.put("Tree.openIcon", icon);
    UIManager.put("Tree.leafIcon", icon);
    

    or use something like next:

    @Override
    public Component getTreeCellRendererComponent(JTree tree,
        Object value, boolean selected, boolean expanded,
        boolean leaf, int row, boolean hasFocus) {
            super.getTreeCellRendererComponent(tree, value, selected,expanded, leaf, row, hasFocus);
            DefaultMutableTreeNode nodo = (DefaultMutableTreeNode) value;
            if (tree.getModel().getRoot().equals(nodo)) {
                setIcon(root);
            } else if (nodo.getChildCount() > 0) {
                setIcon(parent);
            } else {
                setIcon(leaf);
            }
            return this;
    }
    

    Also read about rendering mechanism.