树的复选框用CheckboxTreeViewer实现.由于其子类ContainerCheckedTreeViewer在没有选择全部子节点时可以自动将父节点设置成灰选,所以实现树的复选框更多的是用ContainerCheckedTreeViewer.
关于这个ContainerCheckedTreeViewer类我没有在SWT/JFace的API文档中找到,但是在Eclipse中查看源码能找到.
CheckboxTreeViewer的继承类关系图:
TreeView4.java
public class TreeViewer4 {
public static void main(String[] args) {
new TreeViewer4().open();
} public void open() {
final Display display = new Display();
final Shell shell = new Shell();
shell.setSize(300, 300);
// -----------界面核心代码-------------------
shell.setLayout(new FillLayout());
// 用ContainerCheckedTreeViewer完全替换TreeViewer
ContainerCheckedTreeViewer tv = new ContainerCheckedTreeViewer(shell, SWT.BORDER);
tv.setUseHashlookup(true); // 加快查找速度 Tree tree = tv.getTree();
tree.setHeaderVisible(true);
TreeColumn column = new TreeColumn(tree, SWT.LEFT);
column.setText("名称");
column.setWidth(150);
column = new TreeColumn(tree, SWT.LEFT);
column.setText("子结点数");
column.setWidth(80);
column = new TreeColumn(tree, SWT.LEFT);
column.setText("性别");
column.setWidth(40); tv.setContentProvider(new TreeViewerContentProvider());//设置"内容器"
tv.setLabelProvider(new MyTableLableProvider());//设置"标签器"
// 和TableViewer一样,数据的入口也是setInput方法
List<Country> input = (List)DataFactory.createTreeData();
32 tv.setInput(input);
MyActionGroup2 actionGroup = new MyActionGroup2(tv);// 改用另一个ActionGroup
actionGroup.fillContextMenu(new MenuManager());// 将按钮注入到菜单对象中
// -----------END------------------
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
MyActionGroup2.java
public class MyActionGroup2 extends ActionGroup {
private ContainerCheckedTreeViewer tv; public MyActionGroup2(ContainerCheckedTreeViewer tv) {
this.tv = tv;
}
//这个地方直译方法名就是"填充上下文菜单fillContextMenu()传入的是一个菜单管理器的类(接口)"
public void fillContextMenu(IMenuManager mgr) {
MenuManager menuManager = (MenuManager) mgr;
menuManager.add(new SelectAllAction());//通过菜单管理器增加一个"全选"的Action()
menuManager.add(new RemoveEntryAction());//通过菜单管理器增加一个"删除"的Action()
Tree tree = tv.getTree();//getTree()是TreeViewer类下的一个方法. 就是返回这个视图的树形结构.
Menu menu = menuManager.createContextMenu(tree);
tree.setMenu(menu);
} private class SelectAllAction extends Action {//首先继承Action接口
public SelectAllAction() {//首先就是重写这个Action对应的构造方法
setText("勾选当前结点的所有子结点");
} public void run() {//每个Action中都有对应的run()方法.
IStructuredSelection selection = (IStructuredSelection) tv.getSelection();
ITreeEntry entry = (ITreeEntry) (selection.getFirstElement());
tv.setSubtreeChecked(entry, true); // false不勾选
}
} // 删除结点的Action类
private class RemoveEntryAction extends Action {
public RemoveEntryAction() {
setText("删除");
} public void run() {
Object[] checks = tv.getCheckedElements();// 取得被勾选的结点(包括灰选)
if (checks.length == 0) {
MessageDialog.openInformation(null, "提示", "请先勾选记录");
return;
}
List<ITreeEntry> inputList = (List<ITreeEntry>) tv.getInput();
for (Object object : checks) {
if (tv.getGrayed(object))
continue;// 灰选结点不删除
ITreeEntry entry = (ITreeEntry) object;
remove(inputList, entry);
tv.remove(entry);
}
} private void remove(List<ITreeEntry> list, ITreeEntry entry) {
if (list == null)
return;
for (Iterator it = list.iterator(); it.hasNext();) {
ITreeEntry o = (ITreeEntry) it.next();
if (o.getName().equals(entry.getName())) {
it.remove();
return;
} else {
remove(o.getChildren(), entry);
}
}
}
}
}