树的复选框用CheckboxTreeViewer实现.由于其子类ContainerCheckedTreeViewer在没有选择全部子节点时可以自动将父节点设置成灰选,所以实现树的复选框更多的是用ContainerCheckedTreeViewer.
关于这个ContainerCheckedTreeViewer类我没有在SWT/JFace的API文档中找到,但是在Eclipse中查看源码能找到.
CheckboxTreeViewer的继承类关系图:
TreeView4.java
1 public class TreeViewer4 { 2 public static void main(String[] args) { 3 new TreeViewer4().open(); 4 } 5 6 public void open() { 7 final Display display = new Display(); 8 final Shell shell = new Shell(); 9 shell.setSize(300, 300);10 // -----------界面核心代码-------------------11 shell.setLayout(new FillLayout());12 // 用ContainerCheckedTreeViewer完全替换TreeViewer13 ContainerCheckedTreeViewer tv = new ContainerCheckedTreeViewer(shell, SWT.BORDER);14 tv.setUseHashlookup(true); // 加快查找速度15 16 Tree tree = tv.getTree();17 tree.setHeaderVisible(true);18 TreeColumn column = new TreeColumn(tree, SWT.LEFT);19 column.setText("名称");20 column.setWidth(150);21 column = new TreeColumn(tree, SWT.LEFT);22 column.setText("子结点数");23 column.setWidth(80);24 column = new TreeColumn(tree, SWT.LEFT);25 column.setText("性别");26 column.setWidth(40);27 28 tv.setContentProvider(new TreeViewerContentProvider());//设置"内容器"29 tv.setLabelProvider(new MyTableLableProvider());//设置"标签器"30 // 和TableViewer一样,数据的入口也是setInput方法31 Listinput = (List)DataFactory.createTreeData();32 tv.setInput(input);33 MyActionGroup2 actionGroup = new MyActionGroup2(tv);// 改用另一个ActionGroup34 actionGroup.fillContextMenu(new MenuManager());// 将按钮注入到菜单对象中35 // -----------END------------------36 shell.open();37 while (!shell.isDisposed()) {38 if (!display.readAndDispatch())39 display.sleep();40 }41 display.dispose();42 }43 }
MyActionGroup2.java
1 public class MyActionGroup2 extends ActionGroup { 2 private ContainerCheckedTreeViewer tv; 3 4 public MyActionGroup2(ContainerCheckedTreeViewer tv) { 5 this.tv = tv; 6 } 7 //这个地方直译方法名就是"填充上下文菜单fillContextMenu()传入的是一个菜单管理器的类(接口)" 8 public void fillContextMenu(IMenuManager mgr) { 9 MenuManager menuManager = (MenuManager) mgr;10 menuManager.add(new SelectAllAction());//通过菜单管理器增加一个"全选"的Action()11 menuManager.add(new RemoveEntryAction());//通过菜单管理器增加一个"删除"的Action()12 Tree tree = tv.getTree();//getTree()是TreeViewer类下的一个方法. 就是返回这个视图的树形结构.13 Menu menu = menuManager.createContextMenu(tree);14 tree.setMenu(menu);15 }16 17 private class SelectAllAction extends Action {//首先继承Action接口18 public SelectAllAction() {//首先就是重写这个Action对应的构造方法19 setText("勾选当前结点的所有子结点");20 }21 22 public void run() {//每个Action中都有对应的run()方法.23 IStructuredSelection selection = (IStructuredSelection) tv.getSelection();24 ITreeEntry entry = (ITreeEntry) (selection.getFirstElement());25 tv.setSubtreeChecked(entry, true); // false不勾选26 }27 }28 29 // 删除结点的Action类30 private class RemoveEntryAction extends Action {31 public RemoveEntryAction() {32 setText("删除");33 }34 35 public void run() {36 Object[] checks = tv.getCheckedElements();// 取得被勾选的结点(包括灰选)37 if (checks.length == 0) {38 MessageDialog.openInformation(null, "提示", "请先勾选记录");39 return;40 }41 ListinputList = (List ) tv.getInput();42 for (Object object : checks) {43 if (tv.getGrayed(object))44 continue;// 灰选结点不删除45 ITreeEntry entry = (ITreeEntry) object;46 remove(inputList, entry);47 tv.remove(entry);48 }49 }50 51 private void remove(List list, ITreeEntry entry) {52 if (list == null)53 return;54 for (Iterator it = list.iterator(); it.hasNext();) {55 ITreeEntry o = (ITreeEntry) it.next();56 if (o.getName().equals(entry.getName())) {57 it.remove();58 return;59 } else {60 remove(o.getChildren(), entry);61 }62 }63 }64 }65 }