1

I have a problem with adding new nodes to an existing tree. My tree is based on the CheckBoxNodeTreeSample you can see in the link:

http://www.java2s.com/Code/Java/Swing-JFC/CheckBoxNodeTreeSample.htm

I'm simply trying to add a new node by doing the 'standard' thing:

DefaultTreeModel model = (DefaultTreeModel) this.view.getResultTree().getModel();
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("newNode");
        root.add(newNode);
        model.reload(root);

This works fine, a new node is added, but the difference from the other existing nodes is that I can't click the checkbox, it's not clickable. I tried to print the path of the new node and an existing node, it looks like this:

newNode
Model.CheckBoxNode[Person,..../true]

I been trying to solve this for some time now, but I can't see how to solve this.. Some help would be appreciated! :)

Should i try to add vectors like this? and might this be why the standard solution doesn't work? Been trying this, but the model doesn't like vectors, objects or anything like that.. Casting isn't working either. This is the initialization of the tree, and how they use vectors and checkboxnodes :

CheckBoxNode accessibilityOptions[] = {
    new CheckBoxNode(
        "Move system caret with focus/selection changes", false),
    new CheckBoxNode("Always expand alt text for images", true) };
CheckBoxNode browsingOptions[] = {
    new CheckBoxNode("Notify when downloads complete", true),
    new CheckBoxNode("Disable script debugging", true),
    new CheckBoxNode("Use AutoComplete", true),
    new CheckBoxNode("Browse in a new process", false) };
Vector accessVector = new NamedVector("Accessibility",
    accessibilityOptions);
Vector browseVector = new NamedVector("Browsing", browsingOptions);
Object rootNodes[] = { accessVector, browseVector };
Vector rootVector = new NamedVector("Root", rootNodes);
JTree tree = new JTree(rootVector);

CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
tree.setCellRenderer(renderer);

tree.setCellEditor(new CheckBoxNodeEditor(tree));
tree.setEditable(true);
cloms
  • 89
  • 2
  • 10
  • for better help sooner post an [SSCCE](http://sscce.org/), short, runnable, compilable, just about a.m. issue, before anything to read Oracle tutorials about JTree, JTable and Jlist, JComboBox, because renderers and editor concept is very similair for JComboBox, JList, JTable and JTree.... – mKorbel Sep 30 '13 at 08:46
  • Been reading a lot now but don't feel I'm any closer to the solution.. What I can do now is add the new node as a child of the selected node, but it's still not clickable. This does mean that the getTreeCellEditorComponent() in class CheckBoxNodeEditor doesn't consider the new nodes at all. Doesn't the editor 'work' for all nodes in the tree? – cloms Sep 30 '13 at 13:02
  • it should be, I haven't an issue with, to try to search how to use notifiers about node is added, changed – mKorbel Sep 30 '13 at 13:05
  • Very strange.. I'm guessing I can't create a new listener for each new node. However the node is clickable, and it prints out the value when clicking it. It's just the little checkbox that's not clickable. – cloms Sep 30 '13 at 13:25

2 Answers2

1

Just in case if you didn't find any proper answer, here is a post I asked and answered how to build checkbox tree:

LINK

It might help you

Community
  • 1
  • 1
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • I could paste the existing example from the link and add the 5 lines of code above to create a SSCCE, but that won't be so short. I have a JLIst aswell working nicely, it's just adding a new node and making that checkbox clickable that's really bothering me. I have been reading a lot about Jtree and JComboBox, and learned a few tricks one the way but didn't find a solution to this. I have seen your post before Maxim! I think it's impressive, but I need some time to understand all the things the code is doing. It seems like a lot of work compared to the code I have been using. Thanks! – cloms Sep 30 '13 at 09:06
  • Yes, took me a lot of time to sort things out, especially when you select 1 checkbox from group the root checkbox should be blue. BTW this is a reason that i wrote `Just in case if you didn't find any proper answer`, sorry, don't have time to solve your real issue – Maxim Shoustin Sep 30 '13 at 09:21
0

I made an SSCCE. There is a button you can click to add a new node, with a checkbox but it's not clickable. I'm not creating a jcheckbox anywhere, so don't really understand where I should put an extra listener, and don't understand why it doesn't use getTreeCellEditorComponent() in the editor?

I also tried a slightly different approach where I use model.insertNodeInto(), but still I can't click the checkbox. I believe that I should be able to create a checkboxNode instead of a DefaultMutableTreeNode, but the JTree model doesn't want that, therefore trying to cast it to a DefaultMutableTreeNode.. Anyways, thanks for your help so far!

UPDATE:Because the new node is not of type CheckBoxNode. Therefore listeners doesn't work on the nodes. So now I'm looking for solutions to create a CheckBoxNode[], add it to a Vector, and then add that as a node (it that is possible!). That's how the author made the JTree, so I guess something like that could be the answer!

 import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    import java.awt.event.MouseEvent;
    import java.util.EventObject;
    import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

    public class CheckBoxNodeTreeSample {

    private static JTree tree;

  public static void main(String args[]) {
    JFrame frame = new JFrame("CheckBox Tree");

    CheckBoxNode accessibilityOptions[] = {
        new CheckBoxNode(
            "Move system caret with focus/selection changes", false),
        new CheckBoxNode("Always expand alt text for images", true) };
    CheckBoxNode browsingOptions[] = {
        new CheckBoxNode("Notify when downloads complete", true),
        new CheckBoxNode("Disable script debugging", true),
        new CheckBoxNode("Use AutoComplete", true),
        new CheckBoxNode("Browse in a new process", false) };
    Vector accessVector = new NamedVector("Accessibility",
        accessibilityOptions);
    Vector browseVector = new NamedVector("Browsing", browsingOptions);
    Object rootNodes[] = { accessVector, browseVector };
    Vector rootVector = new NamedVector("Root", rootNodes);
    tree = new JTree(rootVector);

    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    tree.setCellRenderer(renderer);

    tree.setCellEditor(new CheckBoxNodeEditor(tree));
    tree.setEditable(true);

    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.NORTH);

    JPanel buttonPanel = new JPanel();
    JButton button = new JButton("new node");
    buttonPanel.add(button);
    frame.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
            DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New node");
            root.add(newNode);
            model.reload();


        }
    });

    frame.setSize(300, 450);
    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) {

    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 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() {
    JCheckBox checkbox = renderer.getLeafRenderer();
    CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(),
        checkbox.isSelected());
    return checkBoxNode;
  }

  public boolean isCellEditable(EventObject event) {
    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 DefaultMutableTreeNode)) {
          DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
          Object userObject = treeNode.getUserObject();
          returnValue = ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode));
        }
      }
    }
    return returnValue;
  }

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

    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 NamedVector extends Vector {
  String name;

  public NamedVector(String name) {
    this.name = name;
  }

  public NamedVector(String name, Object elements[]) {
    this.name = name;
    for (int i = 0, n = elements.length; i < n; i++) {
      add(elements[i]);
    }
  }

  public String toString() {
    return "[" + name + "]";
  }
}
cloms
  • 89
  • 2
  • 10
  • Trying a new solution based on the same example, you can find it here: http://stackoverflow.com/questions/1223188/jtree-with-checkboxes?rq=1 – cloms Oct 02 '13 at 09:26