 | 级别: 中级 George Kyriacou, 可靠性测试工程师, IBM
2009 年 7 月 23 日 本文解释如何在 Standard Widget Toolkit (SWT) 中开发和实现树。了解如何创建 SWT 树并使用数据进行填充,如何使用列对数据进行分类,如何扩展树以支持行排序,以及如何搜索树的内容。
Standard Widget Toolkit (SWT) 是一个多操作系统图形用户界面 (GUI) 工具包,支持开发人员访问不同的底层平台的本机部件和图形组件,使用 Java™ 作为其惟一的编程语言。
SWT 最初的开发目的是供 Eclipse 项目使用,但是,多年来它已经演变为一个独立的工具包,可用于需要高级 GUI 实现的任何应用程序,这些应用程序具有其所在平台的本机观感。
由于 IBM® Lotus® Expeditor 工具包基于 Eclipse 平台,您需要很好地掌握 SWT 工具包的应用知识,以便能够开发使用 IBM Lotus 和 IBM WebSphere® 产品构建的复合应用程序和插件。
本文主要讨论树,树是 SWT 的一个方面,图 1 给出了树的一种示例结构。
图 1. SWT 树示例
SWT 树的一个较困难的方面是实现树项目的排序,对于这个主题,公共支持论坛中提供的信息难以满足广大用户的需求。本文详细讨论 SWT 中有用的树特性。本文可作为现有内容的补充,将使您能够快速掌握并在自己的复合应用程序中使用树。
方法和前提条件
本文通过代码片段逐步讲述树的各个方面。我们还将使用屏幕截图来帮助更好地描述实现过程。最终解决方案是完整的,可将其轻松集成到任何现有 SWT 应用程序中。
要从本文获得最大收获,您应该对 Java 编程语言拥有一定的了解,并基本了解 SWT 工具包。本文假设您已经熟悉在 Eclipse 中进行 Java 开发,还假设您知道如何将项目链接到 SWT 工具包。如需更多信息,请参考 使用 Eclipse 开发 SWT 应用程序。
理解树
GUI 应用程序中的树提供了一种直观的数据导航方式,它将信息组织到一个分层结构中。在处理特定数据集时,您可以让任何不必要的信息保持隐藏,而不会阻碍处理过程。一个例子是 Eclipse 中的 Preferences 窗口(参见图 2)。
图 2. Eclipse Preferences 窗口
基本 SWT 树
我们首先来看一个基本的 SWT 树。清单 1 中的代码是 SWT 中的一个基本树的示例。
Listing 1. Basic tree implementation
1:import org.eclipse.swt.SWT;
2:import org.eclipse.swt.layout.FillLayout;
3:import org.eclipse.swt.widgets.Display;
4:import org.eclipse.swt.widgets.Shell;
5:import org.eclipse.swt.widgets.Tree;
6:import org.eclipse.swt.widgets.TreeItem;
7:
8:public class First {
9: public static void main(String[] args) {
10: Display display = new Display();
11:
12: Shell shell = new Shell(display);
13: shell.setText("SWT Trees");
14: shell.setLayout(new FillLayout());
15: shell.setSize(400, 300);
16:
17: Tree tree = new Tree(shell, SWT.BORDER);
18:
19: for (int i = 0; i < 5; i++) {
20: TreeItem treeItem = new TreeItem(tree, 0);
21: treeItem.setText("TreeItem" + i);
22: for (int j = 0; j < 5; j++) {
23: TreeItem subTreeItem = new TreeItem(treeItem, SWT.NONE);
24: subTreeItem.setText("SubTreeItem" + j);
25: for (int k = 0; k < 5; k++) {
26: TreeItem subSubTreeItem = new TreeItem(subTreeItem,
27: SWT.NONE);
28: subSubTreeItem.setText("SubSubTreeItem" + k);
29: }
30: }
31: }
32:
33: shell.open();
34: while (!shell.isDisposed()) {
35: if (!display.readAndDispatch())
36: display.sleep();
37: }
38: display.dispose();
39: }
40:}
|
我们通过实例化 Tree 类(清单 1 中的第 17 行)创建一个树,并通过实例化 TreeItem 类(第 20、23 和 26 行)创建树的分支。图 3 展示了当示例在 Microsoft® Windows® 上运行时,该基本树如何显示。
图 3. 基本树
具有列的基本树
列可用于分类数据。清单 2 中的代码示例展示了如何向树中添加列。
清单 2. 具有列的基本树
1:import java.util.Random;
2:
3:import org.eclipse.swt.SWT;
4:import org.eclipse.swt.layout.FillLayout;
5:import org.eclipse.swt.widgets.Display;
6:import org.eclipse.swt.widgets.Shell;
7:import org.eclipse.swt.widgets.Tree;
8:import org.eclipse.swt.widgets.TreeColumn;
9:import org.eclipse.swt.widgets.TreeItem;
10:
11:public class Columns {
12: public static void main(String[] args) {
13: Display display = new Display();
14:
15: Shell shell = new Shell(display);
16: shell.setText("Basic Tree with Columns");
17: shell.setLayout(new FillLayout());
18: shell.setSize(400, 300);
19:
20: Tree tree = new Tree(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
21: tree.setHeaderVisible(true);
22:
23: TreeColumn column1 = new TreeColumn(tree, SWT.NONE);
24: column1.setText("TreeColumn0");
25: column1.setWidth(200);
26: column1.setAlignment(SWT.LEFT);
27:
28: TreeColumn column2 = new TreeColumn(tree, SWT.NONE);
29: column2.setText("TreeColumn1");
30: column2.setWidth(200);
31: column2.setAlignment(SWT.CENTER);
32:
33: Random generator = new Random();
34:
35: for (int i = 0; i < 5; i++) {
36: TreeItem treeItem = new TreeItem(tree, 0);
37: treeItem.setText(new String[] { "TreeItem" + i,
38: Integer.toString(generator.nextInt()) });
39: for (int j = 0; j < 5; j++) {
40: TreeItem subTreeItem = new TreeItem(treeItem, SWT.NONE);
41: subTreeItem.setText(new String[] { "SubTreeItem" + j,
42: Integer.toString(generator.nextInt()) });
43: for (int k = 0; k < 5; k++) {
44: TreeItem subSubTreeItem = new TreeItem(subTreeItem,
45: SWT.NONE);
46: subSubTreeItem.setText(new String[] { "SubSubTreeItem" + k,
47: Integer.toString(generator.nextInt()) });
48: }
49: }
50: }
51:
52: shell.open();
53: while (!shell.isDisposed()) {
54: if (!display.readAndDispatch())
55: display.sleep();
56: }
57: display.dispose();
58: }
59:}
|
我们通过实例化 TreeColumn 类(第 23 和 28 行)来向树中添加列。注意,设置列的宽度(第 25 和 30 行)很重要,如果未设置宽度,列将不会正确显示。而且,树的标题必须设置为可视的(第 21 行),以显示列的标题。
要设置每列的数据,必须将一个 String 类型的数组传递给各个树项目的 setText 方法(第 27、41 和 46 行)。此处,我们使用一个随机整数作为第二列的值(参见图 4)。
图 4. 具有列的基本树
排序树
要对 SWT 树添加排序功能,我们必须实现一个选择监听器,只要选中树的一列就会调用这个监听器。清单 3 展示了一个选择监听器的示例代码,这个监听器可用于对示例应用程序的列进行排序。
清单 3. 排序树选择监听器实现
1:import java.text.Collator;
2:import java.util.Locale;
3:import java.util.regex.Pattern;
4:
5:import org.eclipse.swt.SWT;
6:import org.eclipse.swt.events.SelectionEvent;
7:import org.eclipse.swt.events.SelectionListener;
8:import org.eclipse.swt.widgets.Tree;
9:import org.eclipse.swt.widgets.TreeColumn;
10:import org.eclipse.swt.widgets.TreeItem;
11:
12:public class SortTreeListener implements SelectionListener {
13: @Override
14: public void widgetDefaultSelected(SelectionEvent e) {
15:
16: }
17:
18: @Override
19: public void widgetSelected(SelectionEvent e) {
20: sortTree(e);
21: }
22:
23: private void sortTree(SelectionEvent e) {
24: TreeColumn column = (TreeColumn) e.widget;
25: Tree tree = column.getParent();
26: TreeItem[] treeItems = tree.getItems();
27: TreeColumn sortColumn = tree.getSortColumn();
28: TreeColumn columns[] = tree.getColumns();
29: tree.setSortColumn(column);
30: int numOfColumns = columns.length;
31: int columnIndex = this.findColumnIndex(columns, column, numOfColumns);
32: Collator collator = Collator.getInstance(Locale.getDefault());
33: Boolean sort = false;
34: Pattern pattern = Pattern.compile("([\\+]*|[\\-]*)\\d+");
35: if ((column.equals(sortColumn)) &&
(tree.getSortDirection() == SWT.UP)) {
36: tree.setSortDirection(SWT.DOWN);
37: for (int i = 1; i < treeItems.length; i++) {
38: String value1 = treeItems[i].getText(columnIndex).trim();
39: for (int j = 0; j < i; j++) {
40: String value2 = treeItems[j].getText(columnIndex).trim();
41: if (pattern.matcher(value1).matches()
42: && pattern.matcher(value2).matches()) {
43: double d1 = this.getDouble(value1);
44: double d2 = this.getDouble(value2);
45: if (d1 > d2) {
46: sort = true;
47: }
48: } else if (collator.compare(value1, value2) > 0) {
49: sort = true;
50: }
51: if (sort) {
52: String[] values = this.getColumnValues(treeItems[i],
53: numOfColumns);
54: TreeItem[] subItems = treeItems[i].getItems();
55: TreeItem item = new TreeItem(tree, SWT.NONE, j);
56: item.setText(values);
57: for (TreeItem si : subItems) {
58: TreeItem[] subSubItems = si.getItems();
59: TreeItem subItem = new TreeItem(item, SWT.NONE);
60: subItem.setText(this.getColumnValues(si, numOfColumns));
61: for (TreeItem ssi : subSubItems) {
62: TreeItem subSubItem = new TreeItem(subItem,
63: SWT.NONE);
64: subSubItem.setText(this.getColumnValues(ssi,
65: numOfColumns));
66: }
67: }
68: treeItems[i].dispose();
69: treeItems = tree.getItems();
70: sort = false;
71: break;
72: }
73: }
74: }
75: } else {
76: tree.setSortDirection(SWT.UP);
77: for (int i = 1; i < treeItems.length; i++) {
78: String value1 = treeItems[i].getText(columnIndex).trim();
79: for (int j = 0; j < i; j++) {
80: String value2 = treeItems[j].getText(columnIndex).trim();
81: if (pattern.matcher(value1).matches()
82: && pattern.matcher(value2).matches()) {
83: double d1 = this.getDouble(value1);
84: double d2 = this.getDouble(value2);
85: if (d1 < d2) {
86: sort = true;
87: }
88: } else if (collator.compare(value1, value2) < 0) {
89: sort = true;
90: }
91: if (sort) {
92: String[] values = this.getColumnValues(treeItems[i],
93: numOfColumns);
94: TreeItem[] subItems = treeItems[i].getItems();
95: TreeItem item = new TreeItem(tree, SWT.NONE, j);
96: item.setText(values);
97: for (TreeItem si : subItems) {
98: TreeItem[] subSubItems = si.getItems();
99: TreeItem subItem = new TreeItem(item, SWT.NONE);
100: subItem.setText(this.getColumnValues(si, numOfColumns));
101: for (TreeItem ssi : subSubItems) {
102: TreeItem subSubItem = new TreeItem(subItem,
103: SWT.NONE);
104: subSubItem.setText(this.getColumnValues(ssi,
105: numOfColumns));
106: }
107: }
108: treeItems[i].dispose();
109: treeItems = tree.getItems();
110: sort = false;
111: break;
112: }
113: }
114: }
115: }
116: }
117:
118: /**
119: * Find the index of a column
120: *
121: * @param columns
122: * @param numOfColumns
123: * @return int
124: */
125: private int findColumnIndex(TreeColumn[] columns, TreeColumn column,
126: int numOfColumns) {
127: int index = 0;
128: for (int i = 0; i < numOfColumns; i++) {
129: if (column.equals(columns[i])) {
130: index = i;
131: break;
132: }
133: }
134: return index;
135: }
136:
137: /**
138: * Get the double value from a string
139: *
140: * @param str
141: * @return double
142: */
143: private double getDouble(String str) {
144: double d;
145: if (str.startsWith("+")) {
146: d = Double.parseDouble(str.split("\\+")[1]);
147: } else {
148: d = Double.parseDouble(str);
149: }
150: return d;
151: }
152:
153: /**
154: * Get the array of string value from the provided TreeItem
155: *
156: * @param treeItem
157: * @param numOfColumns
158: * @return String[]
159: */
160: private String[] getColumnValues(TreeItem treeItem, int numOfColumns) {
161: String[] values = new String[numOfColumns];
162: for (int i = 0; i < numOfColumns; i++) {
163: values[i] = treeItem.getText(i);
164: }
165: return values;
166: }
167:}
|
我们做的第一件事是调用 SelectionEvent 的 widget() 函数来确定选定了哪一列(清单 3 中的第 24 行)。
然后,你必须收集树项目和树的列信息(第 25 - 31 行)。此处,我们必须在所选列在树中出现的位置找到该列的索引。因为 TreeColumn 或 Tree 类中没有方法能够提供此信息,您必须比较树的所有列与选定列,并找到正确的索引号,以确定列 ID。
findColumnIndex 方法(第 125 行)就是用于执行这一步的。必须找到列索引来提取该列的文本内容。然后使用该内容来比较每一列,以确定该列在排序树中的正确位置。
您必须检查要排序的选定列是否刚好在已排序的列的前面,如果是这样,还需要确定已经排序的列的排序方向(升序或降序)。这个条件如第 35 行所示,其中,如果在一段连续的时间内对该列排序,并且以前的排序方向为升序,那么它必须切换为降序排序。对于其他任何情况,树必须按升序排序(第 75 - 116 行)。
此外,它必须确定存储在被排序的列中的值是否为数字。将数字作为文本对待会产生错误结果,尤其是当这些值是有符号数字时,因此,列文本必须转换为数字类型。
要确定一列是否包含一个数字,可以使用一个正则表达式(第 34 行)。如果模式匹配(第 41 和 84 行),那么将该列的值存储在一个双精度类型的变量中(第 43、44、83、84 行),使用 getDouble(String str) 方法(第 143 行)。
排序通过对树项目进行迭代(第 37 -39 行)来执行。对存储在列中的所有值进行两两比较(第 45、48、85 和 88 行)。如果两个项目需要调换位置,一个布尔排序变量将设置为 true(第 46、49、86 和 89 行)。当排序变量设置为 true 时,会按照正确的顺序将两个受影响的项目重新创建为新的树项目,旧项目将从树中删除(第 51 - 67 和 91 - 107 行)。
要设置显示列的排序方向的箭头,可以调用 Tree 类的 setSortDirection(int direction) 方法(第 36、37 行)。
要对列启用排序功能,您必须在调用 Shell.open() 方法前向 main 方法中添加以下代码:
column1.addSelectionListener(new SortTreeListener());
column2.addSelectionListener(new SortTreeListener());
清单 4 展示了具有列的基本树的完整实现,其中,列排序功能添加在第 27 和 33 行。
清单 4. 添加了列排序功能的基本树
1:import java.util.Random;
2:
3:import org.eclipse.swt.SWT;
4:import org.eclipse.swt.layout.FillLayout;
5:import org.eclipse.swt.widgets.Display;
6:import org.eclipse.swt.widgets.Shell;
7:import org.eclipse.swt.widgets.Tree;
8:import org.eclipse.swt.widgets.TreeColumn;
9:import org.eclipse.swt.widgets.TreeItem;
10:
11:public class Sorting {
12: public static void main(String[] args) {
13: Display display = new Display();
14:
15: Shell shell = new Shell(display);
16: shell.setText("Sorting Trees");
17: shell.setLayout(new FillLayout());
18: shell.setSize(400, 300);
19:
20: Tree tree = new Tree(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
21: tree.setHeaderVisible(true);
22:
23: TreeColumn column1 = new TreeColumn(tree, SWT.NONE);
24: column1.setText("TreeColumn0");
25: column1.setWidth(200);
26: column1.setAlignment(SWT.LEFT);
27: column1.addSelectionListener(new SortTreeListener());
28:
29: TreeColumn column2 = new TreeColumn(tree, SWT.NONE);
30: column2.setText("TreeColumn1");
31: column2.setWidth(200);
32: column2.setAlignment(SWT.CENTER);
33: column2.addSelectionListener(new SortTreeListener());
34:
35: Random generator = new Random();
36:
37: for (int i = 0; i < 5; i++) {
38: TreeItem treeItem = new TreeItem(tree, 0);
39: treeItem.setText(new String[] { "TreeItem" + i,
40: Integer.toString(generator.nextInt()) });
41: for (int j = 0; j < 5; j++) {
42: TreeItem subTreeItem = new TreeItem(treeItem, SWT.NONE);
43: subTreeItem.setText(new String[] { "SubTreeItem" + j,
44: Integer.toString(generator.nextInt()) });
45: for (int k = 0; k < 5; k++) {
46: TreeItem subSubTreeItem = new TreeItem(subTreeItem,
47: SWT.NONE);
48: subSubTreeItem.setText(new String[] { "SubSubTreeItem" + k,
49: Integer.toString(generator.nextInt()) });
50: }
51: }
52: }
53:
54: shell.open();
55: while (!shell.isDisposed()) {
56: if (!display.readAndDispatch())
57: display.sleep();
58: }
59: display.dispose();
60: }
61:}
|
图 5 展示了一个具有列排序功能的基本树。
图 5. 具有列排序功能的基本树
展开和折叠所有树项目
可以向应用程序中添加一个有用的特性,那就是展开或折叠所有顶级树项目的功能。为此,您可以添加两个按钮:一个用于展开所有顶级树项目,一个用于折叠树项目。清单 5 中的代码是如何实现此特性的一个示例。
清单 5. 树项目的展开和折叠功能的实现
1:import java.util.Random;
2:
3:import org.eclipse.swt.SWT;
4:import org.eclipse.swt.events.SelectionEvent;
5:import org.eclipse.swt.events.SelectionListener;
6:import org.eclipse.swt.layout.GridData;
7:import org.eclipse.swt.layout.GridLayout;
8:import org.eclipse.swt.widgets.Button;
9:import org.eclipse.swt.widgets.Display;
10:import org.eclipse.swt.widgets.Shell;
11:import org.eclipse.swt.widgets.Tree;
12:import org.eclipse.swt.widgets.TreeColumn;
13:import org.eclipse.swt.widgets.TreeItem;
14:
15:public class ExpandAll {
16: private static Tree tree = null;
17:
18: public static void main(String[] args) {
19: Display display = new Display();
20:
21: Shell shell = new Shell(display);
22: shell.setText("Expand All Items");
23: GridLayout gridLayout = new GridLayout();
24: gridLayout.numColumns = 2;
25: shell.setLayout(gridLayout);
26: shell.setSize(400, 300);
27:
28: Button expButton = new Button(shell, SWT.PUSH);
29: expButton.setText("+");
30: GridData gridData = new GridData(23, 23);
31: expButton.setLayoutData(gridData);
32: expButton.addSelectionListener(new ExpandAllItemsListener(true));
33:
34: Button colButton = new Button(shell, SWT.PUSH);
35: colButton.setText("-");
36: gridData = new GridData(23, 23);
37: colButton.setLayoutData(gridData);
38: colButton.addSelectionListener(new ExpandAllItemsListener(false));
39:
40: tree = new Tree(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
41: tree.setHeaderVisible(true);
42:
43: gridData = new GridData(GridData.FILL_BOTH);
44: gridData.horizontalSpan = 2;
45: tree.setLayoutData(gridData);
46:
47: TreeColumn column1 = new TreeColumn(tree, SWT.NONE);
48: column1.setText("TreeColumn0");
49: column1.setWidth(200);
50: column1.setAlignment(SWT.LEFT);
51: column1.addSelectionListener(new SortTreeListener());
52:
53: TreeColumn column2 = new TreeColumn(tree, SWT.NONE);
54: column2.setText("TreeColumn1");
55: column2.setWidth(200);
56: column2.setAlignment(SWT.CENTER);
57: column2.addSelectionListener(new SortTreeListener());
58:
59: Random generator = new Random();
60:
61: for (int i = 0; i < 5; i++) {
62: TreeItem treeItem = new TreeItem(tree, 0);
63: treeItem.setText(new String[] { "TreeItem" + i,
64: Integer.toString(generator.nextInt()) });
65: for (int j = 0; j < 5; j++) {
66: TreeItem subTreeItem = new TreeItem(treeItem, SWT.NONE);
67: subTreeItem.setText(new String[] { "SubTreeItem" + j,
68: Integer.toString(generator.nextInt()) });
69: for (int k = 0; k < 5; k++) {
70: TreeItem subSubTreeItem = new TreeItem(subTreeItem,
71: SWT.NONE);
72: subSubTreeItem.setText(new String[] { "SubSubTreeItem" + k,
73: Integer.toString(generator.nextInt()) });
74: }
75: }
76: }
77:
78: shell.open();
79: while (!shell.isDisposed()) {
80: if (!display.readAndDispatch())
81: display.sleep();
82: }
83: display.dispose();
84: }
85:
86: static class ExpandAllItemsListener implements SelectionListener {
87: private boolean expand = false;
88:
89: public ExpandAllItemsListener(Boolean expand) {
90: this.expand = expand;
91: }
92:
93: @Override
94: public void widgetDefaultSelected(SelectionEvent e) {
95: expandTreeItems();
96: }
97:
98: @Override
99: public void widgetSelected(SelectionEvent e) {
100: expandTreeItems();
101: }
102:
103: public void expandTreeItems() {
104: TreeItem[] treeItems = tree.getItems();
105: if (treeItems != null) {
106: for (TreeItem treeItem : treeItems) {
107: treeItem.setExpanded(expand);
108: }
109: }
110: }
111: }
112:}
|
第一步是添加两个按钮(清单 5 中的第 28 - 38 行),用于展开或折叠树的所有项目。接下来是实现一个选择监听器(第 86 - 111 行),这个监听器在选中一个按钮时执行。
SelectionListener 实现的构造函数接受一个布尔变量,该变量定义要展开还是折叠树项目,具体取决于选中了哪个按钮。expandTreeItems() 方法(第 103 行)对 TreeItems 数组进行迭代,并调用 TreeItem 类的 setExpanded(boolean expanded) 方法(第 107 行),传递由类的构造函数设置的布尔变量。
要获得顶级树项目的数组,您可以调用 Tree 类的 getItems() 方法(第 104 行)。
图 6 展示了一个树,其中展开了所有 TreeItems。
图 6. 展开了 TreeItems 的树
搜索树
您可以向应用程序添加的另一项特性是搜索功能,该功能对于用户必须处理大型数据集时尤为有用。
清单 6 中的代码展示了如何实现一个监听器来搜索树的顶级元素。
清单 6. 搜索树项目监听器
1:import org.eclipse.jface.dialogs.InputDialog;
2:import org.eclipse.swt.SWT;
3:import org.eclipse.swt.events.KeyEvent;
4:import org.eclipse.swt.events.KeyListener;
5:import org.eclipse.swt.widgets.MessageBox;
6:import org.eclipse.swt.widgets.Tree;
7:import org.eclipse.swt.widgets.TreeItem;
8:
9:public class SearchListener implements KeyListener {
10: private Tree tree = null;
11:
12: @Override
13: public void keyPressed(KeyEvent e) {
14: tree = (Tree) e.widget;
15:
16: String searchString = showSearchPopup();
17: if (searchString == null) {
18: return;
19: }
20:
21: if (!findString(searchString, tree.getItems())) {
22: MessageBox messageBox = new MessageBox(tree.getShell(), SWT.OK
23: | SWT.ICON_ERROR);
24: messageBox.setMessage("Could not find: '" + searchString + "'");
25: messageBox.setText("Search Error");
26: messageBox.open();
27: }
28:
29: }
30:
31: @Override
32: public void keyReleased(KeyEvent e) {
33:
34: }
35:
36: private String showSearchPopup() {
37: InputDialog d = new InputDialog(this.tree.getParent().getShell(),
38: "Search", "Search text", "", null);
39: d.open();
40: return d.getValue();
41: }
42:
43: private boolean findString(String searchString, TreeItem[] treeItems) {
44: for (TreeItem treeItem : treeItems) {
45: for (int i = 0; i < tree.getColumnCount(); i++) {
46: String text = treeItem.getText(i);
47: if ((text.toUpperCase().contains(searchString.toUpperCase()))) {
48: tree.setSelection(treeItem);
49: return true;
50: }
51: }
52: }
53:
54: return false;
55: }
56:}
|
此监听器可以作为一个 KeyListener 添加到树中,这样,当用户输入一些内容并选中树的一个项目时,输入窗口将会显示如图 7 所示的结果。
图 7. 搜索窗口
算法很简单,它对树的顶级项目进行迭代,并将其文本内容与搜索字符串进行比较(清单 6 中的第 43 -52 行)。当在一个树项目中找到搜索字符串时,将会选定该树项目(第 48 行)。如果未找到该字符串,将会显示一个 Search Error 消息 “Could not find: 'TreeItemX'”(第 21 - 27 行)。
现在,惟一要修改的地方是将 SearchListener 添加到树的关键监听器集合中,如清单 7 中的第 23 行所示。
清单 7. 基本树搜索
1:import java.util.Random;
2:
3:import org.eclipse.swt.SWT;
4:import org.eclipse.swt.layout.FillLayout;
5:import org.eclipse.swt.widgets.Display;
6:import org.eclipse.swt.widgets.Shell;
7:import org.eclipse.swt.widgets.Tree;
8:import org.eclipse.swt.widgets.TreeColumn;
9:import org.eclipse.swt.widgets.TreeItem;
10:
11:public class Searching {
12: public static void main(String[] args) {
13: Display display = new Display();
14:
15: Shell shell = new Shell(display);
16: shell.setText("Searching");
17: shell.setLayout(new FillLayout());
18: shell.setSize(400, 300);
19:
20: Tree tree = new Tree(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
21: | SWT.FULL_SELECTION);
22: tree.setHeaderVisible(true);
23: tree.addKeyListener(new SearchListener());
24:
25: TreeColumn column1 = new TreeColumn(tree, SWT.NONE);
26: column1.setText("TreeColumn0");
27: column1.setWidth(200);
28: column1.setAlignment(SWT.LEFT);
29: column1.addSelectionListener(new SortTreeListener());
30:
31: TreeColumn column2 = new TreeColumn(tree, SWT.NONE);
32: column2.setText("TreeColumn1");
33: column2.setWidth(200);
34: column2.setAlignment(SWT.CENTER);
35: column2.addSelectionListener(new SortTreeListener());
36:
37: Random generator = new Random();
38:
39: for (int i = 0; i < 5; i++) {
40: TreeItem treeItem = new TreeItem(tree, 0);
41: treeItem.setText(new String[] { "TreeItem" + i,
42: Integer.toString(generator.nextInt()) });
43: for (int j = 0; j < 5; j++) {
44: TreeItem subTreeItem = new TreeItem(treeItem, SWT.NONE);
45: subTreeItem.setText(new String[] { "SubTreeItem" + j,
46: Integer.toString(generator.nextInt()) });
47: for (int k = 0; k < 5; k++) {
48: TreeItem subSubTreeItem = new TreeItem(subTreeItem,
49: SWT.NONE);
50: subSubTreeItem.setText(new String[] { "SubSubTreeItem" + k,
51: Integer.toString(generator.nextInt()) });
52: }
53: }
54: }
55:
56: shell.open();
57: while (!shell.isDisposed()) {
58: if (!display.readAndDispatch())
59: display.sleep();
60: }
61: display.dispose();
62: }
63:}
|
最后,只要对搜索算法进行简单修改就可以对所有树项目执行递归搜索。
结束语
SWT 树是组织并向用户呈现数据的一种非常有效的方式。使用本文中的信息和代码示例,您可以增强并充分利用您的复合应用程序和基于 SWT 的应用程序。
致谢
作者特别感谢 Gary Denner 的不断支持和在写作本文时提供的帮助。
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | George Kyriacou 在获得了圣三一学院的计算机科学专业理学硕士之后,于 2008 年加入位于爱尔兰都柏林的 IBM 软件实验室。他目前担任 IBM Lotus Domino System Test 团队的可靠性测试工程师,开发工具来改进对 Lotus Notes 和 Lotus Domino 的测试。 |
对本文的评价
|  |