Solved

getUserObject returns null

Posted on 2010-11-15
28
551 Views
Last Modified: 2012-08-13
I'm trying to change my JTree into a CheckBoxNodeTree.

I've added some print statements and it prints:

... In isCellEditable ...
... In isCellEditable:node:1.3.12.2.1107.5.1.4.54567.30000010080311570664000000016
... In isCellEditable:treeNode:1.3.12.2.1107.5.1.4.54567.30000010080311570664000000016
... In isCellEditable:userObject:null

The code for this is below.

What would be the reason for the userObject being null?

0
Comment
Question by:mock5c
  • 12
  • 10
  • 6
28 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 34141670
Have you got the code for this???
0
 
LVL 92

Expert Comment

by:objects
ID: 34141759
how are you setting it?
0
 

Author Comment

by:mock5c
ID: 34142111
Well, I threw together this code which I believe shows userObject as null.  Most of the code is from a checkbox tree node sample I found online and I'm trying to incorporate that into my code.  This sample code however is not graphical.
import java.awt.event.*;
import java.awt.*;

import java.util.*;
import java.io.*;
import java.net.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.SwingUtilities;
import javax.swing.tree.*;
import javax.swing.event.*;

public class MySample{
  public static void main(String args[]){

    MyTreeNode rootNode = new MyTreeNode();
    rootNode.setNodeName("Root");
    rootNode.setType("root");

    MyTreeNode chNode1 = new MyTreeNode();
    rootNode.setNodeName("ch1");
    rootNode.setType("leaf");

    MyTreeNode chNode2 = new MyTreeNode();
    rootNode.setNodeName("ch2");
    rootNode.setType("leaf");

    rootNode.add(chNode1);
    rootNode.add(chNode2);

    DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
    JTree tree = new JTree(treeModel);
    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    tree.setCellRenderer(renderer);
    tree.setCellEditor(new CheckBoxNodeEditor(tree));
    tree.setEditable(true);
    tree.setShowsRootHandles(true);
  }
}

class CheckBoxNodeRenderer implements TreeCellRenderer {

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

  protected JCheckBox getLeafRenderer()
  {
    return leafRenderer;
  }

  public CheckBoxNodeRenderer() {
    Font fontValue;
    fontValue = UIManager.getFont("Tree.font");
    if (fontValue != null) {
      leafRenderer.setFont(fontValue);
    }
    Boolean booleanValue = (Boolean) UIManager
        .get("Tree.drawsFocusBorderAroundIcon");
    leafRenderer.setFocusPainted((booleanValue != null)
        && (booleanValue.booleanValue()));

    selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
    selectionForeground = UIManager.getColor("Tree.selectionForeground");
    selectionBackground = UIManager.getColor("Tree.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) {

      System.out.println("   VALUE1   " + value);
    Component returnValue;

    if (leaf) {
      String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, false);
      leafRenderer.setText(stringValue);
      leafRenderer.setSelected(false);

      System.out.println("   VALUE2   " + value);

      leafRenderer.setEnabled(tree.isEnabled());

      if (selected) {
        leafRenderer.setForeground(selectionForeground);
        leafRenderer.setBackground(selectionBackground);
      }
      else {
        leafRenderer.setForeground(textForeground);
        leafRenderer.setBackground(textBackground);
      }

      if (value != null && (value instanceof DefaultMutableTreeNode)) {
        System.out.println("This is a DefaultMutableTreeNode");

        Object userObject = ((DefaultMutableTreeNode) value)
            .getUserObject();
 
        System.out.println("value ***" + value);
        System.out.println("userObject ***" + userObject);

      }
      if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
        Object userObject = ((DefaultMutableTreeNode) value)
            .getUserObject();
        if (userObject instanceof CheckBoxNode) {
          CheckBoxNode node = (CheckBoxNode) userObject;
          leafRenderer.setText(node.getText());
          leafRenderer.setSelected(node.isSelected());
        }
      }
      returnValue = leafRenderer;
    }
    else {
      returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
          value, selected, expanded, leaf, row, hasFocus);
    }
    return returnValue;
  }
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

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

  public CheckBoxNodeEditor(JTree tree) {
    this.tree = tree;
  }

  public Object getCellEditorValue() {
    System.out.println("... In getCellEditorValue ...");
    JCheckBox checkbox = renderer.getLeafRenderer();
    DefaultMutableTreeNode checkBoxNode = new DefaultMutableTreeNode();
    return checkBoxNode;
  }

  public boolean isCellEditable(EventObject event) {
    System.out.println("... In isCellEditable ...");
    boolean returnValue = false;
    if (event instanceof MouseEvent) {
      MouseEvent mouseEvent = (MouseEvent) event;
      TreePath path = tree.getPathForLocation(mouseEvent.getX(),
          mouseEvent.getY());
      if (path != null) {
        Object node = path.getLastPathComponent();
        System.out.println("... In isCellEditable:node:" + node);
        if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
          DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
          Object userObject = treeNode.getUserObject();
          System.out.println("... In isCellEditable:treeNode:" + treeNode);
          System.out.println("... In isCellEditable:userObject:" + userObject);
          returnValue = ((treeNode.isLeaf()) && (userObject instanceof DefaultMutableTreeNode));
        }
      }
    }
    return returnValue;
  }

  public Component getTreeCellEditorComponent(JTree tree, Object value,
      boolean selected, boolean expanded, boolean leaf, int row) {
    System.out.println("... In getTreeCellEditorComponent ...");

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

    // editor always selected / focused
    ItemListener itemListener = new ItemListener() {
      public void itemStateChanged(ItemEvent itemEvent) {
        if (stopCellEditing()) {
          fireEditingStopped();
        }
      }
    };
    if (editor instanceof JCheckBox) {
      ((JCheckBox) editor).addItemListener(itemListener);
    }

    return editor;
  }
}

class CheckBoxNode {
  String text;

  boolean selected;

  public CheckBoxNode(String text, boolean selected) {
    this.text = text;
    this.selected = selected;
  }

  public boolean isSelected() {
    return selected;
  }

  public void setSelected(boolean newValue) {
    selected = newValue;
  }

  public String getText() {
    return text;
  }

  public void setText(String newValue) {
    text = newValue;
  }

  public String toString() {
    return getClass().getName() + "[" + text + "/" + selected + "]";
  }
}

class MyTreeNode extends DefaultMutableTreeNode
{

  private String type = null;
  private String nodeName = null;
  private ArrayList<TreeNode> children = new ArrayList();
  private TreeNode parent = null;
  private String nodeId = null;
  private boolean selected = false;

  public void setNodeId(String nodeId)
  {
    this.nodeId = nodeId;
  }

  public String getNodeId()
  {
    return nodeId;
  }

  public void setType(String type)
  {
    this.type = type;
  }

  public String getType()
  {
    return this.type;
  }

  public void setNodeName(String name)
  {
    this.nodeName = name;
  }

  public String getNodeName()
  {
    return this.nodeName;
  }

  public void add(MyTreeNode node)
  {
    if (children == null)
    {
      children = new ArrayList();
    }
    System.out.println("adding :" + node.getNodeName() + " to " + nodeName);
    children.add(node);
    System.out.println("Child count for :" + nodeName + " is now: " + children.size());
  }

  public void setParent(TreeNode parent)
  {
    this.parent = parent;
  }

  public Enumeration children()
  {
    Enumeration e = Collections.enumeration(children);
    System.out.println("children() :" + nodeName + " : " + e);
    return e;
  }

  public boolean getAllowsChildren()
  {
    System.out.println("getAllowsChildren() :" + nodeName);
    boolean retVal = true;

    if (type.equals("leaf"))
    {
      retVal = false;
    }     

    return true;
  }

  public TreeNode getChildAt(int childIndex)
  {
    System.out.println("getChildAt() :" + nodeName);
    TreeNode retVal = null;

    if (childIndex < children.size() && childIndex >= 0)
    {
      retVal = children.get(childIndex);
    }

    return retVal;
  }

  public int getChildCount()
  {
    System.out.println("getChildCount() :" + nodeName + " : " + children.size());
    int retVal = 0;
    
    if (children != null)
    {
      retVal = children.size();
    }

    return retVal;
  }

  public int getIndex(TreeNode node)
  {
    System.out.println("getIndex() :" + nodeName);
    int retVal = -1;

    if (children != null)
    {
      for (int i=0; i < children.size(); i++)
      {
        TreeNode childNode = children.get(i);
        if (childNode == node)
        {
          retVal = i;
          break;
        }
      }
    }  
 
    return retVal;
  }

  public TreeNode getParent()
  {
    System.out.println("getParent() :" + nodeName);
    return parent;
  }

  public boolean isLeaf()
  {
    boolean retVal = false;

    if (type.equals("leaf"))
    {
      retVal = true;
    }

    System.out.println("isLeaf() :" + nodeName + " : " + retVal);
    return retVal;
  }

  public boolean isSelected()
  {
    return selected;
  }

  public void setSelected(boolean newValue)
  {
    selected = newValue;
  }

  public String toString()
  {
    return this.nodeName;
  }
}

Open in new window

0
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 35

Expert Comment

by:mccarl
ID: 34142138
> What would be the reason for the userObject being null?

Maybe, because you are setting userObject to anything?
0
 
LVL 92

Expert Comment

by:objects
ID: 34142150
you never set the user object (via setUserObject())
it is as the name suggests a user object, it does not get set for you. Its there for you to use however you see fit
Its useful for avoinding having to subclass DefaultMutableTreeNode
0
 

Author Comment

by:mock5c
ID: 34142212
In this code (http://www.java2s.com/Code/Java/Swing-JFC/CheckBoxNodeTreeSample.htm)

where is the userObject being set?  If I understand you correctly, this is why my sample code failed.  This is the code I'm trying to incorporate into my program.
0
 
LVL 92

Assisted Solution

by:objects
objects earned 75 total points
ID: 34142246
the codes making the assumption that the tree data provided to create the tree will be set as the user object of the tree nodes (created inside the tree constructor).
0
 
LVL 35

Assisted Solution

by:mccarl
mccarl earned 425 total points
ID: 34142562
To expand on what objects is saying, in the sample code the tree is being built by supplying it with a vector of vectors. Now I couldn't find it in the doco, but what is happening is that the JTree constructor that takes the vector argument, builds the tree nodes from the vectors contents and as it is doing so sets the user object to the current object from the vector that it is processing.

Whereas you are supplying the JTree constructor with the tree nodes already created and so it isn't doing anything else for you. The easiest way that I can see to make your program work would be to change the "if" block that is between lines 112 - 120 in the code that you posted, to the below... (i.e. don't worry about userObject at all, because the "value" object that is passed to you is the MyTreeNode object that you created at the start so you can just call the methods on that)


if ((value != null) && (value instanceof MyTreeNode)) {
        MyTreeNode node = (MyTreeNode) value;
        leafRenderer.setText(node.getNodeName());
        leafRenderer.setSelected(node.isSelected());
      }

Open in new window

0
 

Author Comment

by:mock5c
ID: 34147278
I've made those modifications, which make sense.  In my app., don't see the checkboxes changing checked to not check or vice versa.  I'm actually looking at the CheckBoxNodeTreeSample.java (from the link I sent) and don't see where it actually calls CheckBoxNode.setSelected().  There are calls to leafRenderer.setSelected() but that's a JCheckBox, not a CheckBoxNode.  I'm not sure how it is able to set this value in the node and remember the setting.

I'm upping the points.
0
 

Author Comment

by:mock5c
ID: 34148569
It seems that I have to have this userObject business in order to allow the checkboxes to be toggled.   In the CheckBoxNodeTreeSample.java code that I found on the web, I modifed the code below to what mccarl suggested and I can no longer check/uncheck the check box nodes.  

/*original code*/
      if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
        Object userObject = ((DefaultMutableTreeNode) value)
            .getUserObject();
        if (userObject instanceof CheckBoxNode) {
          CheckBoxNode node = (CheckBoxNode) userObject;
          leafRenderer.setText(node.getText());
          leafRenderer.setSelected(node.isSelected());
        }      
      }
/* new code */

      if ((value != null) && (value instanceof CheckBoxNode)) {
        CheckBoxNode node = (CheckBoxNode) value;
        leafRenderer.setText(node.getText());
        leafRenderer.setSelected(node.isSelected());
      }

So this leads me to ask if there's a way to get this userObject functionality without the whole vector arugment in the constructor.  I think having a vector will require too many modifications to my existing code.
0
 
LVL 92

Expert Comment

by:objects
ID: 34150474
code at that link works fine for me

problem with your code is that you don't create any CheckBoxNodes

your MyTreeNode class also seems redundant as it duplicates all the functionality already provided by the parent class
0
 

Author Comment

by:mock5c
ID: 34150653
MyTreeNode has additional private member variables and functions.  So I'm creating those instead of CheckBoxNodes.  Is there anything special about the CheckBoxNode class?  I'm not seeing anything.
0
 
LVL 92

Expert Comment

by:objects
ID: 34150748
> MyTreeNode has additional private member variables and functions.

yes but you also re-implement whats already in DMTN
The usual way to do what you are doing is to use the user object instead of subclassing (as has been done in the example you are using)

>  Is there anything special about the CheckBoxNode class?  I'm not seeing anything.

Yes, it indicates which nodes to render as checkboxes and includes the name and whether it is selected
0
 
LVL 92

Expert Comment

by:objects
ID: 34150753
>       if ((value != null) && (value instanceof CheckBoxNode)) {

There are no CheckBoxNodes in your tree so this will always be false
0
 

Author Comment

by:mock5c
ID: 34150760
The sample program I provided obviously doesn't help since it's not bringing up any GUI.  However, in the code to that link (CheckBoxNodeTreeSample.java), have you modified it and removed userObject and changed to

if ((value != null) && (value instanceof CheckBoxNode)) {
        CheckBoxNode node = (CheckBoxNode) value;
        leafRenderer.setText(node.getText());
        leafRenderer.setSelected(node.isSelected());
      }

Can you check/uncheck the nodes after doing that?
0
 
LVL 92

Expert Comment

by:objects
ID: 34150873
>   However, in the code to that link (CheckBoxNodeTreeSample.java), have you modified it and removed userObject and changed to

no theres no need, it works fine.

changing it to that will stop it working as the tree noes are DMTN's (not CheckBoxNode's)
0
 

Author Comment

by:mock5c
ID: 34151005
The reason I'm making the changes is simply just for testing purposes.  As mccarl said, "what is happening is that the JTree constructor that takes the vector argument, builds the tree nodes from the vectors contents and as it is doing so sets the user object to the current object from the vector that it is processing.", I figured I someone need these userObjects in order to get these checkboxes work.  I was simply trying to modify the code from the link so it did not have use the userObject code but still allow clicking.  It seems I need these userObjects to work with MyTreeNode the way I'm setting JTree.
0
 
LVL 92

Expert Comment

by:objects
ID: 34151079
you need something on your node to indicate whether it is selected or not
0
 

Author Comment

by:mock5c
ID: 34151103
I have boolean selected member data and void setSelected(boolean), boolean isSelected() methods.
0
 
LVL 35

Expert Comment

by:mccarl
ID: 34151124
On line 163, of the code that you posted above (note that the code that working with at the moment, that line will be at a different number) have you changed ...

returnValue = ((treeNode.isLeaf()) && (userObject instanceof DefaultMutableTreeNode));

to

returnValue = (treeNode.isLeaf());
0
 
LVL 92

Expert Comment

by:objects
ID: 34151180
>         CheckBoxNode node = (CheckBoxNode) value;

you should be casting it to your tree node subclass instead then

0
 

Author Comment

by:mock5c
ID: 34151182
Yes.  See the isCellEditable method below that I currently have.
public boolean isCellEditable(EventObject event) {
    System.out.println("... In isCellEditable ...");
    boolean returnValue = false;
    if (event instanceof MouseEvent) {
      MouseEvent mouseEvent = (MouseEvent) event;
      TreePath path = tree.getPathForLocation(mouseEvent.getX(),
          mouseEvent.getY());
      if (path != null) { 
        Object node = path.getLastPathComponent();

        if ((node != null) && (node instanceof MyTreeNode)) {
          MyTreeNode treeNode = (MyTreeNode) node;
          returnValue = treeNode.isLeaf();
        }       
      }
    }
    return returnValue;
  }

Open in new window

0
 

Author Comment

by:mock5c
ID: 34151495
by the way, I do see the checkbox nodes in the tree and when I click on them, they get depressed and everything.   I just can't seem to get the checkmarks to show up.  I'm trying to understand if this userObject is required for that.
0
 
LVL 92

Expert Comment

by:objects
ID: 34151571
no they won't because you need to change the renderer to work with your node subclass (instead of DMTN as in the example). See my earlier comment regards what you need to change

0
 

Author Comment

by:mock5c
ID: 34151955
I assume you're talking about casting to my tree node subclass.  This is the CheckBoxNodeRenderer code I've been using:
class CheckBoxNodeRenderer implements TreeCellRenderer {

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

  protected JCheckBox getLeafRenderer()
  {
    return leafRenderer;
  }

  public CheckBoxNodeRenderer() {
    Font fontValue;
    fontValue = UIManager.getFont("Tree.font");
    if (fontValue != null) {
      leafRenderer.setFont(fontValue);
    }
    Boolean booleanValue = (Boolean) UIManager
        .get("Tree.drawsFocusBorderAroundIcon");
    leafRenderer.setFocusPainted((booleanValue != null)
        && (booleanValue.booleanValue()));

    selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
    selectionForeground = UIManager.getColor("Tree.selectionForeground");
    selectionBackground = UIManager.getColor("Tree.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) {       
      String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, false);
      leafRenderer.setText(stringValue);
      leafRenderer.setSelected(false);
      leafRenderer.setEnabled(tree.isEnabled());
                      
      if (selected) { 
        leafRenderer.setForeground(selectionForeground);
        leafRenderer.setBackground(selectionBackground);
      }
      else {
        leafRenderer.setForeground(textForeground);
        leafRenderer.setBackground(textBackground);
      }
      
      if (value != null && (value instanceof MyTreeNode)) {
        System.out.println("... instanceof This is a MyTreeNode");
        MyTreeNode node = (MyTreeNode) value;
        leafRenderer.setText(node.getNodeName());
        leafRenderer.setSelected(node.isSelected());
      }
      returnValue = leafRenderer;
    }   
    else {
      returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
          value, selected, expanded, leaf, row, hasFocus); 
    }   
    return returnValue;
  }     
}

Open in new window

0
 
LVL 35

Accepted Solution

by:
mccarl earned 425 total points
ID: 34152050
I have been playing with this trying to work out what is going wrong (I can reproduce your symptoms) and I think I have found the answer.

In the CellEditor class, getCellEditorValue() is supposed to return a value which represents the newly edited state. However, the tree doesn't replace the tree nodes that you originally created with this value, it sets the value returned as the userObject.

So basically what your program is doing differently to the original sample code, is that your program keeps rendering a checkbox who's state never changes, whereas the sample code renders checkboxes who's state comes from the userObject, and it's this userObject that gets changed in the getCellEditorValue() method.

Since JTree obviously (after working all this out for myself) has a lot of assumptions on what the userObject is for, I would recommend that the best approach would be to refactor back to using the userObject. I have attached a slightly modified version of your originally posted code, that keeps your MyTreeNode class (for storing whatever attributes against it) but includes setting the userObject to a CheckBoxNode to keep track of the selected state. Notice the main differences from the sample code is that setUserObject is explicitly called on your MyTreeNodes at the start (hence emulating what the constructor with vector argument was doing)


import java.awt.event.*;
import java.awt.*;

import java.util.*;
import java.io.*;
import java.net.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.SwingUtilities;
import javax.swing.tree.*;
import javax.swing.event.*;

public class MySample{
  public static void main(String args[]){

    MyTreeNode rootNode = new MyTreeNode();
    rootNode.setNodeName("Root");
    rootNode.setType("root");

    MyTreeNode chNode1 = new MyTreeNode();
    chNode1.setNodeName("ch1");
    chNode1.setType("leaf");
    chNode1.setUserObject(new CheckBoxNode("ch1", false));

    MyTreeNode chNode2 = new MyTreeNode();
    chNode2.setNodeName("ch2");
    chNode2.setType("leaf");
    chNode2.setUserObject(new CheckBoxNode("ch2", false));

    rootNode.add(chNode1);
    rootNode.add(chNode2);

    DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
    JTree tree = new JTree(treeModel);
    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    tree.setCellRenderer(renderer);
    tree.setCellEditor(new CheckBoxNodeEditor(tree));
    tree.setEditable(true);
    tree.setShowsRootHandles(true);

    JFrame frame = new JFrame("CheckBox Tree");
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}

class CheckBoxNodeRenderer implements TreeCellRenderer {

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

  protected JCheckBox getLeafRenderer()
  {
    return leafRenderer;
  }

  public CheckBoxNodeRenderer() {
    Font fontValue;
    fontValue = UIManager.getFont("Tree.font");
    if (fontValue != null) {
      leafRenderer.setFont(fontValue);
    }
    Boolean booleanValue = (Boolean) UIManager
        .get("Tree.drawsFocusBorderAroundIcon");
    leafRenderer.setFocusPainted((booleanValue != null)
        && (booleanValue.booleanValue()));

    selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
    selectionForeground = UIManager.getColor("Tree.selectionForeground");
    selectionBackground = UIManager.getColor("Tree.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) {

      System.out.println("   VALUE1   " + value);
    Component returnValue;

    if (leaf) {
      String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, false);
      leafRenderer.setText(stringValue);
      leafRenderer.setSelected(false);

      System.out.println("   VALUE2   " + value);

      leafRenderer.setEnabled(tree.isEnabled());

      if (selected) {
        leafRenderer.setForeground(selectionForeground);
        leafRenderer.setBackground(selectionBackground);
      }
      else {
        leafRenderer.setForeground(textForeground);
        leafRenderer.setBackground(textBackground);
      }

      if (value != null && (value instanceof DefaultMutableTreeNode)) {
        System.out.println("This is a DefaultMutableTreeNode");

        Object userObject = ((DefaultMutableTreeNode) value)
            .getUserObject();

        System.out.println("value ***" + value);
        System.out.println("userObject ***" + userObject);

      }
      if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
        Object userObject = ((DefaultMutableTreeNode) value)
            .getUserObject();
        if (userObject instanceof CheckBoxNode) {
          CheckBoxNode node = (CheckBoxNode) userObject;
          leafRenderer.setText(node.getText());
          leafRenderer.setSelected(node.isSelected());
        }
      }
      returnValue = leafRenderer;
    }
    else {
      returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
          value, selected, expanded, leaf, row, hasFocus);
    }
    return returnValue;
  }
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

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

  public CheckBoxNodeEditor(JTree tree) {
    this.tree = tree;
  }

  public Object getCellEditorValue() {
    System.out.println("... In getCellEditorValue ...");
    JCheckBox checkbox = renderer.getLeafRenderer();
    CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(),
        checkbox.isSelected());
    return checkBoxNode;
  }

  public boolean isCellEditable(EventObject event) {
    System.out.println("... In isCellEditable ...");
    boolean returnValue = false;
    if (event instanceof MouseEvent) {
      MouseEvent mouseEvent = (MouseEvent) event;
      TreePath path = tree.getPathForLocation(mouseEvent.getX(),
          mouseEvent.getY());
      if (path != null) {
        Object node = path.getLastPathComponent();
        System.out.println("... In isCellEditable:node:" + node);
        if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
          DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
          Object userObject = treeNode.getUserObject();
          System.out.println("... In isCellEditable:treeNode:" + treeNode);
          System.out.println("... In isCellEditable:userObject:" + userObject);
          returnValue = ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode));
        }
      }
    }
    return returnValue;
  }

  public Component getTreeCellEditorComponent(JTree tree, Object value,
      boolean selected, boolean expanded, boolean leaf, int row) {
    System.out.println("... In getTreeCellEditorComponent ...");

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

    // editor always selected / focused
    ItemListener itemListener = new ItemListener() {
      public void itemStateChanged(ItemEvent itemEvent) {
        if (stopCellEditing()) {
          fireEditingStopped();
        }
      }
    };
    if (editor instanceof JCheckBox) {
      ((JCheckBox) editor).addItemListener(itemListener);
    }

    return editor;
  }
}

class CheckBoxNode {
  String text;

  boolean selected;

  public CheckBoxNode(String text, boolean selected) {
    this.text = text;
    this.selected = selected;
  }

  public boolean isSelected() {
    return selected;
  }

  public void setSelected(boolean newValue) {
    selected = newValue;
  }

  public String getText() {
    return text;
  }

  public void setText(String newValue) {
    text = newValue;
  }

  public String toString() {
    return getClass().getName() + "[" + text + "/" + selected + "]";
  }
}

class MyTreeNode extends DefaultMutableTreeNode
{

  private String type = null;
  private String nodeName = null;
  private ArrayList<TreeNode> children = new ArrayList();
  private TreeNode parent = null;
  private String nodeId = null;
  private boolean selected = false;

  public void setNodeId(String nodeId)
  {
    this.nodeId = nodeId;
  }

  public String getNodeId()
  {
    return nodeId;
  }

  public void setType(String type)
  {
    this.type = type;
  }

  public String getType()
  {
    return this.type;
  }

  public void setNodeName(String name)
  {
    this.nodeName = name;
  }

  public String getNodeName()
  {
    return this.nodeName;
  }

  public void add(MyTreeNode node)
  {
    if (children == null)
    {
      children = new ArrayList();
    }
    System.out.println("adding :" + node.getNodeName() + " to " + nodeName);
    children.add(node);
    System.out.println("Child count for :" + nodeName + " is now: " + children.size());
  }

  public void setParent(TreeNode parent)
  {
    this.parent = parent;
  }

  public Enumeration children()
  {
    Enumeration e = Collections.enumeration(children);
    System.out.println("children() :" + nodeName + " : " + e);
    return e;
  }

  public boolean getAllowsChildren()
  {
    System.out.println("getAllowsChildren() :" + nodeName);
    boolean retVal = true;

    if (type.equals("leaf"))
    {
      retVal = false;
    }

    return true;
  }

  public TreeNode getChildAt(int childIndex)
  {
    System.out.println("getChildAt() :" + nodeName);
    TreeNode retVal = null;

    if (childIndex < children.size() && childIndex >= 0)
    {
      retVal = children.get(childIndex);
    }

    return retVal;
  }

  public int getChildCount()
  {
    System.out.println("getChildCount() :" + nodeName + " : " + children.size());
    int retVal = 0;

    if (children != null)
    {
      retVal = children.size();
    }

    return retVal;
  }

  public int getIndex(TreeNode node)
  {
    System.out.println("getIndex() :" + nodeName);
    int retVal = -1;

    if (children != null)
    {
      for (int i=0; i < children.size(); i++)
      {
        TreeNode childNode = children.get(i);
        if (childNode == node)
        {
          retVal = i;
          break;
        }
      }
    }

    return retVal;
  }

  public TreeNode getParent()
  {
    System.out.println("getParent() :" + nodeName);
    return parent;
  }

  public boolean isLeaf()
  {
    boolean retVal = false;

    if (type.equals("leaf"))
    {
      retVal = true;
    }

    System.out.println("isLeaf() :" + nodeName + " : " + retVal);
    return retVal;
  }

  public boolean isSelected()
  {
    return selected;
  }

  public void setSelected(boolean newValue)
  {
    selected = newValue;
  }

  public String toString()
  {
    return this.nodeName;
  }
}

Open in new window

0
 

Author Comment

by:mock5c
ID: 34152507
mccarl, that did the trick.  I am able to tick/untick the checkboxes.  It seems that they are toggled whenever I highlight the node, whether I click on the node row or the checkbox.  Is it possible to have it so the checkbox is checked only if the checkbox itself is checked?
0
 
LVL 35

Expert Comment

by:mccarl
ID: 34152539
I think this is just standard JCheckbox behaviour, in that clicking the label or the box toggled the state (you can verify that in a normal Swing app)

The only thing I can think of is instead of creating a JCheckbox in your Renderer/Editor code, you define a custom component which is a JPanel which contains a JCheckbox with empty label and then a JLabel with the label that you want. You can therefore create instances of the custom component instead. Maybe you can find more info on the web about stopping hits on the label of a JCheckbox toggling the state.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question