javaswingjlabeljtreetreecellrenderer

JLabel within JTree won't resize when content changes


I have a JTree that behaves like so:

Currently, my code looks like so:

public class TaskTreeCellRenderer extends DefaultTreeCellRenderer {
    private JLabel label;

    public TaskTreeCellRenderer() {
        label = new JLabel();
    }

    public Component getTreeCellRendererComponent(JTree tree,
           Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        Object nodeValue = ((DefaultMutableTreeNode) value).getUserObject();

        if (nodeValue instanceof RootObject) {
            label.setIcon(null);
            label.setText(((RootObject) nodeValue).getTitle());
        } else if (nodeValue instanceof ChildObject) {
            ChildObject thisChild = (ChildObject) nodeValue;

            if (thisChild.isRunning()) {
                label.setIcon(new ImageIcon(getClass().getResource("arrow.png")));
                label.setText("<html><nobr><b>" + thisChild.getName() + "</b></nobr></html>");
            } else if (thisChild.isComplete()) {
                label.setIcon(new ImageIcon(getClass().getResource("check.png")));
                label.setText("<html><nobr><i>" + thisChild.getName() + "</i></nobr></html>");
            } else {
                label.setIcon(null);
                label.setText(thisChild.getName());
            }
        }

        return label;
    }
}

For the most part, this renders fine. The initial tree renders fine with the labels using plaintext. The problem is once the ChildObject instances start changing state, the JLabels update to use HTML rendering, but don't resize to compensate for the text or icon. For example:

Initial state:
http://imageshack.us/a/img14/3636/psxi.png

In progress:
http://imageshack.us/a/img36/7426/bl8.png

Finished:
http://imageshack.us/a/img12/4117/u34l.png

Any ideas where I'm going wrong? Thanks in advance!


Solution

  • So you need to tell the tree model that the content is changed. Each time if the status of your ChildObject is changed you must do following:

    ((DefaultTreeModel)tree.getModel()).reload(node);
    

    Where node is the DefaultMutableTreeNode, which contains the changed ChildObject.

    Don't forget to use SwingUtilities.invokeLater() if the Status of child object is changed outside of the Swing-Thread (EDT).