Jtree renderers


Rexx Magnus

I'm having problems writing a custom JTree renderer.

I have created code for a tree that displays checkboxes for true/false
data (represented by checkboxnode types) and one for text and numerical
data which will use a spinner. Problems occur in getCellEditorValue() when
I try to filter out the type of renderer to deal with the input. This is
due to the getLeafRenderer() method.

It only returns leafRenderer, and I can't work out a way of getting it to
return the different types of renderer instead of just one. It needs to
return leafRenderer when it is a checkbox (which works fine if you change
the method's return type to JCheckBox as it was in the example) and
leafSpinRenderer when it is a spinner. There are other ways of finding out
the values, but they reflect the old value (this is in the event handler
and looks messy and incorrect).
Most of the examples of checkbox node trees don't have any explanation of
how the code works, so I'm flying blind.

class CharacterNodeRenderer implements TreeCellRenderer {

private JCheckBox leafRenderer = new JCheckBox();
private JSpinner leafSpinRenderer = new JSpinner();
private DefaultTreeCellRenderer nonLeafRenderer = new
Color selectionBorderColor, selectionForeground, selectionBackground,
textForeground, textBackground;

// ********* this was originally written as protected JCheckBox
getLeafRenderer() in example code.\

protected Object getLeafRenderer() {

return leafRenderer;

public CharacterNodeRenderer() {
Font fontValue;
fontValue = UIManager.getFont("Tree.font");
if (fontValue != null) {
Boolean booleanValue = (Boolean)
leafRenderer.setFocusPainted((booleanValue != null) &&

selectionBorderColor =
selectionForeground =
selectionBackground =
textForeground = UIManager.getColor("Tree.textForeground");
textBackground = UIManager.getColor("Tree.textBackground");

public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {

Component returnValue;
if (leaf & (((DefaultMutableTreeNode) value).getUserObject()
instanceof CheckBoxNode)) {

String stringValue = tree.convertValueToText(value, selected,
expanded, leaf, row, false);


if (selected) {
} else {

//for checkboxes, read the state from the data and set box
if ((value != null) && (value instanceof
DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode)
if (userObject instanceof CheckBoxNode) {
CheckBoxNode node = (CheckBoxNode) userObject;
returnValue = leafRenderer;
//read data for stats and set values
} else if (leaf & (((DefaultMutableTreeNode)
value).getUserObject() instanceof Stat)) {
Object userObject = ((DefaultMutableTreeNode)
Stat node = (Stat) userObject;
returnValue = leafSpinRenderer;
} else {
returnValue =
value, selected, expanded, leaf, row, hasFocus);
return returnValue;

class CharacterNodeEditor extends AbstractCellEditor implements
TreeCellEditor {

CharacterNodeRenderer renderer = new CharacterNodeRenderer();
ChangeEvent changeEvent = null;
JTree tree;

public CharacterNodeEditor(JTree tree) {
this.tree = tree;

public Object getCellEditorValue() {
if (renderer.getLeafRenderer() instanceof JCheckBox){

// ************* this secton works fine if its returning a JCheckBox, but
I don't always want it to.

JCheckBox checkbox = renderer.getLeafRenderer();
CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(),
return checkBoxNode;
else if (renderer.getLeafRenderer() instanceof JSpinner)
// ************* I was going to add different return types for different
node renderers, as you can see

// JSpinner statbox = renderer.getLeafRenderer();
// Stat statnode = new Stat(statbox.getValue());

public boolean isCellEditable(EventObject event) {
boolean returnValue = false;
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
TreePath path = tree.getPathForLocation(mouseEvent.getX(),


if (path != null) {
Object node = path.getLastPathComponent();
if ((node != null) && (node instanceof
DefaultMutableTreeNode)) {
DefaultMutableTreeNode treeNode =
(DefaultMutableTreeNode) node;
Object userObject = treeNode.getUserObject();
returnValue = ((treeNode.isLeaf()) && ((userObject
instanceof CheckBoxNode) || (userObject instanceof Stat)));

return returnValue;

public boolean isCellEditable(EventObject event) {
boolean returnValue = super.isCellEditable(event);
if (returnValue) {
Object node = tree.getLastSelectedPathComponent();
if ((node != null) && (node instanceof TreeNode)) {
TreeNode treeNode = (TreeNode) node;
returnValue = treeNode.isLeaf();
return returnValue;

public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row) {

Component editor = renderer.getTreeCellRendererComponent(tree,
true, expanded, leaf, row, true);

// editor always selected / focused
ItemListener itemListener = new ItemListener() {

public void itemStateChanged(ItemEvent itemEvent) {
if (stopCellEditing()) {
if (editor instanceof JCheckBox) {
((JCheckBox) editor).addItemListener(itemListener);
else if (editor instanceof JSpinner)
((JSpinner) editor).addItemListener(itemListener);
return editor;


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads