I'm using a CheckBoxTree component to get a special kind of JTree with checkboxes. However, I want to be able to have no checkbox on the high level nodes, because they should never be checked, they are just "names of branches". Here's a simple example of the tree:
metadata - product - prod A - prod B - etc - model - etc
The node "metadata" is thus the root of the treemodel. This node is invisible thanks to a convenient setRootVisible method available (as in JTree). But besides making the root invisible I also want to have the second level checkboxes removed. So basically, there should only be checkboxes from the levels from prod A, prod B etc and downwards (can be several levels lower). But I still want the label for level two.
I tried implementing a custom CheckboxTreecellRenderer according to this site that describes the checkboxtree component:
http://www.javaworld.com/javaworld/jw-09-2007/jw-09-checkboxtree.html?page=3
Unfortunately, this doesn't work. Compared to the example on the site, I tried moving the adding of the label and button (I'm not going to use radio buttons, just using it to try to remove the label to keep it simple, but I'm still going to use checkboxes if I get this to work somehow). I moved them in order to try to set a button only if the node had the metadata node as its parent, thus removing buttons from second level.
But this didn't work. Surprisingly, the concept itself seems to work, because the button.setEnabled(false); (Commented out below) does work. That disables buttons on the correct level. But if I try to not add buttons there I get no buttons anywhere...
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package se.expertinfo.ditaplugin;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.CheckboxTree;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.CheckboxTreeCellRenderer;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.TreeCheckingModel;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.TreePath;
/**
*
* @author Anders
*/
public class CustomTreeCellRenderer implements CheckboxTreeCellRenderer {
JPanel panel = new JPanel();
JLabel label = new JLabel();
JRadioButton button = new JRadioButton();
public CustomTreeCellRenderer() {
label.setFocusable(true);
label.setOpaque(true);
panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
// panel.add(button);
// panel.add(label);
button.setBackground(UIManager.getColor("Tree.textBackground"));
panel.setBackground(UIManager.getColor("Tree.textBackground"));
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
label.setText(value.toString());
if (selected) {
label.setBackground(UIManager.getColor("Tree.selectionBackground"));
} else {
label.setBackground(UIManager.getColor("Tree.textBackground"));
}
TreeCheckingModel checkingModel = ((CheckboxTree) tree).getCheckingModel();
TreePath path = tree.getPathForRow(row);
boolean enabled = checkingModel.isPathEnabled(path);
boolean checked = checkingModel.isPathChecked(path);
boolean grayed = checkingModel.isPathGreyed(path);
button.setEnabled(enabled);
if (path != null) {
TreePath parent = path.getParentPath();
if (parent != null) {
if (parent.getLastPathComponent().toString().equalsIgnoreCase("metadata")) {
// button.setEnabled(false);
panel.add(label);
} else {
panel.add(button);
panel.add(label);
button.setSelected(checked);
}
}
}
if (grayed) {
label.setForeground(Color.lightGray);
} else {
label.setForeground(Color.black);
}
button.setSelected(checked);
return panel;
}
@Override
public boolean isOnHotspot(int x, int y) {
return (button.getBounds().contains(x, y));
}
}
This example uses isLeaf()
in the implementation of isCellEditable()
to confine editing to leaf nodes only.
Addendum: To preclude editing above a certain level, you can check the number of elements on the path using a predicate such as this: path.getPathCount() > 2
.