Solved

getUserObject returns null

Posted on 2010-11-15
28
547 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
Comment Utility
Have you got the code for this???
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
how are you setting it?
0
 

Author Comment

by:mock5c
Comment Utility
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
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
> 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
> 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
Comment Utility
>       if ((value != null) && (value instanceof CheckBoxNode)) {

There are no CheckBoxNodes in your tree so this will always be false
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:mock5c
Comment Utility
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
Comment Utility
>   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
Comment Utility
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
Comment Utility
you need something on your node to indicate whether it is selected or not
0
 

Author Comment

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

Expert Comment

by:mccarl
Comment Utility
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
Comment Utility
>         CheckBoxNode node = (CheckBoxNode) value;

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

0
 

Author Comment

by:mock5c
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

For customizing the look of your lightweight component and making it look lucid like it was made of glass. Or: how to make your component more Apple-ish ;) This tip assumes your component to be of rectangular shape and completely opaque. (COD…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

743 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now