I have a JTree that behaves like so:
RootObject
; it uses a plaintext label and is static throughout the lifespan of the tree.ChildObject
, which may be in one of three states: not running, running, or finished.ChildObject
is not running, it's a plaintext label.ChildObject
is running, it uses an icon resource and switches to HTML rendering so the text is in italics.ChildObject
has finished, it uses a different icon resource and uses HTML rendering to show the text in bold.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!
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).