I've got a JTree with icons on some of the nodes within the tree. They appear and work fine but when I select a node with a icon, the renderer does not render the entire node selected but appears to have an offset applied to it, as if it thinks the icon is still to the left of the node as below:
The code for the renderer (which extends DefaultTreeCellRenderer) is below:
public ProfileTreeRenderer() {
super.setLeafIcon(null);
super.setClosedIcon(null);
super.setOpenIcon(null);
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (c instanceof JLabel) {
JLabel label = (JLabel) c;
label.setHorizontalTextPosition(SwingConstants.LEADING);
}
if(sel && !hasFocus) {
setBackgroundSelectionColor(UIManager.getColor("Panel.background"));
setTextSelectionColor(UIManager.getColor("Panel.foreground"));
} else {
setTextSelectionColor(UIManager.getColor("Tree.selectionForeground"));
setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground"));
}
if (value instanceof ProfileNode) {
ProfileNode node = (ProfileNode) value;
if (node.isUsed() && !sel) {
c.setForeground(Color.GRAY);
}
if (node.getIcon() != null) {
setIcon(node.getIcon());
}
}
}
I cannot see why the renderer would apply this offset, so can anyone offer a way to get the node fully selected with the icon? The SSCCE code for the tree itself is below.
public class Example extends JDialog {
public Example() {
JTree tree = new JTree(createModel());
tree.setCellRenderer(new ProfileTreeRenderer());
setLayout(new BorderLayout());
add(tree, BorderLayout.CENTER);
}
private TreeModel createModel() {
ProfileNode root = new ProfileNode("Profiles");
ProfileNode userA = new ProfileNode("Example User A");
ProfileNode userB = new ProfileNode("Example User B");
// You'll need to subsitute your own 16x16 icons here
userA.setIcon(ImageSet.USER_ICON);
userB.setIcon(ImageSet.USER_ICON);
root.add(userA);
root.add(userB);
return new DefaultTreeModel(root);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Example().setVisible(true);
}
});
}
}
The ProfileNode class:
public class ProfileNode extends DefaultMutableTreeNode {
@Getter private String labelDisplay;
@Getter @Setter private ImageIcon icon;
@Getter @Setter private boolean isUsed = false;
public ProfileNode(String labelDisplay) {
this.labelDisplay = labelDisplay;
}
@Override
public String toString() {
return labelDisplay;
}
}
Thanks in advance.