I have an unusual situation where I need to have a JTree with each node containing 2 checkboxes and a label (with the ability to add a listener to tell when any of the poten
This might be a good time to look at the old JTreeTable code, which will give you a tree rendered in the first column, and the freedom to render the cells for each column to the right of the tree node as you wish, in your case putting in checkboxes and a label, and allowing you to have TableCellEditors working with your JTable as you are used to. A warning is that, while the code in that link works, it is a little convoluted.
There is an alternative. I have demoed below a Tree Table implementation that is supposed to be better, called Outline
, provided by NetBeans (though you don't need to develop with the NetBeans IDE, you just need the jar). This article indicates how easy it is to be to get started.
I was able to mock up a quick example of the Outline tree table in Eclipse (with the org-netbeans-swing-outline.jar imported to my project) in about 30 minutes (I am slow at typing):
private void buildFrame() {
frame = new JFrame("Demo");
frame.setSize(300, 300);
addStuffToFrame();
frame.setVisible(true);
}
private void addStuffToFrame() {
MyTreeNode top = new MyTreeNode("top");
createNodes(top);
DefaultTreeModel model = new DefaultTreeModel(top);
//here are the netBeans tree table classes
OutlineModel outlineModel =
DefaultOutlineModel.createOutlineModel(model, new MyRowModel());
Outline outline = new Outline();
outline.setRootVisible(true);
outline.setModel(outlineModel);
frame.getContentPane().add(new JScrollPane(outline));
}
private void createNodes(MyTreeNode top) {
MyTreeNode child = new MyTreeNode("child 2");
top.add(new MyTreeNode("child 1"));
child.add(new MyTreeNode("g-child1"));
child.add(new MyTreeNode("g-child2"));
child.add(new MyTreeNode("g-child3"));
top.add(child);
top.add(new MyTreeNode("child3"));
top.add(new MyTreeNode("child4"));
}
I create a TreeNode to hold the Boolean
s that will interoperate well with the JTable
's built-in checkbox rendering mechnanism.
public class MyTreeNode extends DefaultMutableTreeNode {
Boolean data1 = null;
Boolean data2 = null;
String name = null;
MyTreeNode (String name) {
this.name=name;
}
void setData1(Boolean val) {data1=val;}
void setData2(Boolean val) {data2=val;}
Boolean getData1() {return data1;}
Boolean getData2() {return data2;}
String getName() {return name;}
}
The netBeans RowModel is the key to making this a table instead of a simple JTree:
public class MyRowModel implements RowModel {
public Class getColumnClass(int col) {
switch (col) {
case 0: return String.class;
case 1: return Boolean.class; //these return class definitions will
case 2: return Boolean.class; //trigger the checkbox rendering
default:return null;
}
}
public int getColumnCount() {
return 3;
}
public String getColumnName(int col) {
return "";
}
public Object getValueFor(Object node, int col) {
MyTreeNode n = (MyTreeNode)node;
switch (col) {
case 0: return n.getName();
case 1: return n.getData1();
case 2: return n.getData2();
default:return null;
}
}
public boolean isCellEditable(Object node, int col) {
return col > 0;
}
public void setValueFor(Object node, int col, Object val) {
MyTreeNode n = (MyTreeNode)node;
if (col == 1) {n.setData1((Boolean)val);}
else if (col == 2) {n.setData2((Boolean)val);}
//EDIT: here is a recursive method to set all children
// selected for one of the two checkboxes as it is
// checked by the parent
for (Enumeration children = n.children();
children.hasMoreElements(); ) {
MyTreeNode child = (MyTreeNode) children.nextElement();
setValueFor(child, col, val);
}
}
}
here is the finished, albeit simplistic, product:
alt text http://img17.imageshack.us/img17/6643/picture1hz.png
I have updated the setValueFor
method to iterate over a node's children and set the checkboxes as selected or deselected when a parent has been modified.
It wasn't clear where the buildFrame(), addStuffToFrame() and createNodes() methods go. I put them all into an OutlineJFrame class I created that extends JFrame, and deleted the 'frame.' preface where-ever it appeared. Then in my project's main() method, it just created one of those OutlineJFrame objects and set its visible to true. When it ran, I got a resizable but empty window. Where were the rows? Where were the nodes?
Then I asked Geertjan, the NetBeans guru, what I was doing wrong, and he sent me a re-write. But it had the same behaviour.
But I know that my java is fine, because another demo project I did (FileTreeJFrame) displays outline.java objects just fine.
Take a look at http://www.java2s.com/Code/Java/Swing-JFC/CheckBoxNodeTreeSample.htm