Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

JCheckboxes as JTree nodes

843806Aug 7 2008 — edited Aug 8 2008
Hi all,
This is a code which I got from the forum from Rodney.
I tried modifying the code for certain requirements. Nothing seems to work.

I will list the modifications I tried.

1) When the parent checkbox node is checked, all the child checkboxes should get checked.
2) If all the child checkboxes are checked, the parent checkbox should get checked.
I am posting my SSCE.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.util.EventObject;
 
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
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.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
 
public class CheckBoxNodeTreeSample {
    public static void main(String args[]) {
        JFrame frame = new JFrame("CheckBox Tree");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        DefaultMutableTreeNode accessNode = new DefaultMutableTreeNode(new CheckBoxNode("Accessibility", true));
        accessNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Move system caret with focus/selection changes", true)));
        accessNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Always expand alt text for images", true)));
 
        DefaultMutableTreeNode browseNode = new DefaultMutableTreeNode(new CheckBoxNode("Browsing", true));
        browseNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Notify when downloads complete", true)));
        browseNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Disable script debugging", true)));
        browseNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Use AutoComplete", true)));
        browseNode.add(new DefaultMutableTreeNode(new CheckBoxNode("Browse in a new process", true)));
        
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Root");
        rootNode.add(accessNode);
        rootNode.add(browseNode);
        
        JTree tree = new JTree(rootNode);
        tree.setToggleClickCount(1);
        tree.setRootVisible(false);
        tree.putClientProperty("JTree.lineStyle", "None");
        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.CENTER);
        frame.setSize(400, 300);
        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;
    
    DefaultMutableTreeNode editedNode;
 
    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)) {
                    editedNode = (DefaultMutableTreeNode) node;
                    Object userObject = editedNode.getUserObject();
                    Rectangle r = tree.getPathBounds(path);
                    int x = mouseEvent.getX() - r.x;
                    int y = mouseEvent.getY() - r.y;                    
                    JCheckBox checkbox = renderer.getLeafRenderer();
                    checkbox.setText("");
                    returnValue = userObject instanceof CheckBoxNode && x > 0 && x < checkbox.getPreferredSize().width;
                }
            }
        }
        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()) {
        	        if (!editedNode.isLeaf()) {                        
        	            for (int i = 0; i < editedNode.getChildCount(); i++) {
        	                DefaultMutableTreeNode node = (DefaultMutableTreeNode) editedNode.getChildAt(i);
        	                CheckBoxNode cbn = (CheckBoxNode) node.getUserObject();
        	                cbn.setSelected(renderer.getLeafRenderer().isSelected());
        	            }
        	        }
        	 
        	        if (!renderer.getLeafRenderer().isSelected()) {
        	            DefaultMutableTreeNode node = (DefaultMutableTreeNode) editedNode.getParent();
        	            if (node.getUserObject() instanceof CheckBoxNode)
        	                ((CheckBoxNode) node.getUserObject()).setSelected(false);                            
        	        }
        	            
        	        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 + "]";
    }
}
Please help with the requirements 1 and 2 mentioned above.
Rony
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Sep 5 2008
Added on Aug 7 2008
18 comments
410 views