我有一个不寻常的情况,我需要一个 JTree,每个节点包含 2 个复选框和一个标签(能够添加一个侦听器来告知何时选中任何潜在的复选框)。我还需要根节点具有相同的布局(我假设这意味着创建一个带有 2 个 JCheckBoxes 和一个 JLabel 的 JPanel),如果选中了根中的一个复选框,则能够选择树下的所有复选框。
有什么指导或例子吗?我已经在这里查看了以前的问题和相关示例......其中一些让我能够达到让树“看起来”的目的,但没有给我一个实施它背后的动作的方向。
谢谢!
这可能是查看旧JTreeTable代码的好时机,它将为您提供在第一列中呈现的树,并根据您的情况自由地在树节点右侧呈现每列的单元格放入复选框和标签,并允许您让 TableCellEditors 像您习惯的那样使用您的 JTable。一个警告是,虽然该链接中的代码有效,但它有点令人费解。
有一个替代方案。我在下面演示了一个应该更好的树表实现,称为Outline
,由 NetBeans 提供(尽管您不需要使用 NetBeans IDE 进行开发,您只需要 jar)。 本文表明入门是多么容易。
我能够在大约 30 分钟内模拟出 Eclipse 中 Outline 树表的快速示例(将 org-netbeans-swing-outline.jar 导入到我的项目中)(我打字速度很慢):
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"));
}
我创建了一个 TreeNode 来保存将与' 的内置复选框呈现机制 Boolean
良好互操作的 s。JTable
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;}
}
netBeans RowModel 是使它成为表而不是简单的 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);
}
}
}
这是完成的产品,虽然很简单:
替代文字 http://img17.imageshack.us/img17/6643/picture1hz.png
我更新了setValueFor
迭代节点子节点的方法,并在修改父节点时将复选框设置为选中或取消选中。
尚不清楚 buildFrame()、addStuffToFrame() 和 createNodes() 方法的去向。我将它们全部放入我创建的扩展 JFrame 的 OutlineJFrame 类中,并删除了“框架”。序言无论它出现在哪里。然后在我项目的 main() 方法中,它只是创建了其中一个 OutlineJFrame 对象并将其可见设置为 true。当它运行时,我得到了一个可调整大小但为空的窗口。行在哪里?节点在哪里?
然后我问 NetBeans 大师 Geertjan,我做错了什么,他给我发了一份重新编写的文件。但它具有相同的行为。
但我知道我的 java 很好,因为我做的另一个演示项目(FileTreeJFrame)显示 outline.java 对象就好了。