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