创建虚树与虚表
关键字: virtual tree table
转自: http://liugang594.javaeye.com/blog/159449
构建一棵树或表,有时,如果数据量太大,那么一次性加载所有的数据将耗费大量的时间。SWT中提供了一个虚拟的样式用以推迟对数据的加载,通过这种分散加载的方式来加速树或表的构建和显示。
要实现一棵虚树或一个虚表,我们需要用到VIRTUAL样式。
构建虚树/表的几个需要关键点:
一、VIRTUAL样式的设置
显然这是必须的,例如:
- //构建树
- Tree tree = new Tree(composite, SWT.BORDER | SWT.VIRTUAL);
- //构建表
- Table table = new Table(composite, SWT.BORDER | SWT.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);
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) {
- ……
- }
- }
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);
- }
- }
- }
- });
//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,可以试试它的用法。