构建一棵树或表,有时,如果数据量太大,那么一次性加载所有的数据将耗费大量的时间。SWT中提供了一个虚拟的样式用以推迟对数据的加载,通过这种分散加载的方式来加速树或表的构建和显示。
要实现一棵虚树或一个虚表,我们需要用到VIRTUAL样式。
构建虚树/表的几个需要关键点:
一、VIRTUAL样式的设置
显然这是必须的,例如:
//构建树
Tree tree = new Tree(composite, SWT.BORDER | SWT.VIRTUAL);
//构建表
Table table = new Table(composite, SWT.BORDER | SWT.VIRTUAL);
二、设置显示的Item数
例如:
table.setItemCount(COUNT);
tree.setItemCount(COUNT);
这个也是必须的,因为在下面的SetData事件里需要根据这个Item数来决定监听事件的调用次数。通常这个值设置为树或表最初显示时的可见item数。在不确定的时候要选择一个合适的值来确保显示的正确性。
三、增加SetData监听
以上两步完成后,我们需要增加一个SWT的SetData监听事件来完成最后的任务。例如:
tree.addListener(SWT.SetData, new Listener() {
public void handleEvent(Event event) {
……
}
}
table.addListener(SWT.SetData, new Listener() {
public void handleEvent(Event event) {
……
}
}
这个事件在两种情况下都会被调用:(1)树结点展开的时候。(2)窗口可见的时候。
这个方法就是用来完成具体的当树要显示或者一个结点要打开时,用来计算子结点数和决定各个子结点的内容。
四、记录结点信息
这个很重要,但对于虚树/表本身的构建来说,不属于它的一部分。不过我还是认为这是很重要的。
显然,为了正确构建树结点或树结点的子结点,我们需要有一个记录结点信息的地方,这个见仁见智,各人可能有各人的方法。例如,通常可以使用setData(Object data)方法来记录各个结点的信息,看下面的示例。
四、示例
以树为例,例如显示目录结构的树:
//setData部分
Tree tree = new Tree(shell, SWT.VIRTUAL | SWT.BORDER);
File[] roots = File.listRoots();
tree.setData(roots);
//setItemCount
tree.setItemCount(roots.length);
//监听部分
tree.addListener(SWT.SetData, new Listener() {
public void handleEvent(Event event) {
//event中得到当前正在创建的树结点和它的父结点
TreeItem item = (TreeItem) event.item;
TreeItem parentItem = item.getParentItem();
File file = null;
//如果父结点为null,说明当前结点的树的根结点(可能有多个)
if (parentItem == null) {
/* root-level item */
File[] files = (File[]) tree.getData();
file = files[event.index];
item.setText(file.toString());
}
/*
* 如果父结点不为空,则父结点记录的信息中找到一个
* 正确的信息作为此结点的信息
* 这里index表示此结点的序号
*/
else {
File[] files = (File[]) parentItem.getData();
file = files[event.index];
item.setText(file.getName());
}
//如果是目录,认为它有将有子结点,所以记录它的信息
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
item.setData(files);
item.setItemCount(files.length);
}
}
}
});
对于与虚树/表,JFace里有一个ILazyTreeContentProvider和ILazyContentProvider,可以试试它的用法。