2

I want to have a JTree in my swing application that does not have an icon for leaf nodes, so I wrote the following code:

    DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)
        jtree.getCellRenderer();
    renderer.setLeafIcon(null);
    jtree.setCellRenderer(renderer);

This correctly removes the icons for leaves, but it also results in the following rendering error:

Badly rendered tree

You can see that the labels attached to the branch nodes are truncated, and they are bunched too close together. If I expand and then collapse all the branch nodes, the problem fixes itself:

enter image description here

If I comment out the line:

renderer.setLeafIcon(null);

The problem goes away (but the leaf icon, which I don't want, is present.)

Any ideas how to fix this?

Edit: I'll add all the relevant code.

public class StepChooserPanel extends JScrollPane { 
private JTree rules;

public StepChooserPanel(TabPanel parent){
    super();

    this.setBackground(Color.white);


    DefaultMutableTreeNode top = new DefaultMutableTreeNode("top");
    rules = new JTree();
    rules.getSelectionModel()
        .setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    rules.setRootVisible(false);
    rules.setScrollsOnExpand(false);
    rules.setToggleClickCount(1);
    rules.addTreeSelectionListener(parent);
    rules.putClientProperty("JTree.lineStyle", "None");


    DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)
        rules.getCellRenderer();
    renderer.setLeafIcon(null);
    rules.setCellRenderer(renderer);

    this.setViewportView(rules);

}

public void populateFilterRules(InferenceSystem system){

    DefaultMutableTreeNode root = new DefaultMutableTreeNode();
    TreeModel treeModel = new DefaultTreeModel(root);
    rules.setModel(treeModel);

    List<Rule> systemRules = system.getSortedRules();       
    for(int i = 0; i < systemRules.size(); i++){
        if(!(systemRules.get(i) instanceof InferenceRule)){
            continue;
        }
        DefaultMutableTreeNode rule = new DefaultMutableTreeNode
                (systemRules.get(i).getName());
        root.add(rule);
    }

    rules.expandPath(new TreePath(root.getPath())); 

    this.repaint();     
}

public void populateRewriteList(Collection<Rewrite> choices){

    DefaultMutableTreeNode root = (DefaultMutableTreeNode) rules.getModel()
        .getRoot();

    for(Rewrite rr : choices){
        for (int i = 0; i < root.getChildCount(); i++){
            String ruleName = (String) ((DefaultMutableTreeNode)root.getChildAt(i))
                                    .getUserObject();
            if(rr.getRule().getName().equals(ruleName)){
                ((DefaultMutableTreeNode)root.getChildAt(i))
                    .add(new DefaultMutableTreeNode(rr));
            }
        }           
    }   

    this.repaint();
}

All the setup is done in the constructor. populateFilterRules is called, which adds in the branch nodes. Then populateRewriteList is called, which adds in the leaf nodes to the right places. repaint is called after these changes are made. The containing JScrollPane class is wrapped into a JSplitPane, which is rendered into the frame.

julianfperez
  • 1,726
  • 5
  • 38
  • 69
Oliver
  • 11,297
  • 18
  • 71
  • 121
  • these are hard to track without seeing code - BasicTreeUI does a lot of size caching which is not always cleared when appropriate. Plus some LAFs silently install a fixed rowHeight, which detoriates the problem. – kleopatra Apr 28 '11 at 14:51

2 Answers2

1

This works fine for me. Double check that there is not something else going on.

If you are changing this after the tree has been displayed, make sure you are repainting the tree.

An ugly work around might be a 100% transparent icon instead of null.

jzd
  • 23,473
  • 9
  • 54
  • 76
  • All this config stuff is done before the tree is displayed. I guess it could be a problem with the L&F I am using. – Oliver Apr 28 '11 at 14:36
  • Also, build on the [EDT](http://download.oracle.com/javase/tutorial/uiswing/concurrency/initial.html); `JTree` is especially sensitive to this. – trashgod Apr 28 '11 at 17:10
1

An alternative is to use an implementation having no pixels, as suggested here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045