为了实现这样的效果:
载入的过程中,显示Pending。
载入完毕,Pending消失。
我们先从基础的说起,先来看ITreeContentProvider 接口:
getElements 表示在setInput(Object)的时候,如何从Object中得到一个数组,而使用这个数组去将树的第一层结点显示出来。这个方法只在setInput时才使用一次。
getChildren表示在每次展开树的节点时,如果得到下一级节点的值,当然,树的节点展开了一次就不会再调用这个方法了,因为在树节点对应的控件TreeItem中,已经创建好了子节点控件了。
hasChildren就是判断当前节点是否有子节点,有的话,就显示+号。
ITreeContentProvider的使用类型可以分成3种(我自己分的,^-^)。
1。简单模式
2。Lazy Loader模式(简单)
3。Lazy Loader模式(显示Pending)
一. 简单模式
其实就是在setInput的模型中,已经预先将所有的子模型都载入完毕,而不用再动态的载入子模型了。
模型说明:
这个模型代表树节点,是支持父子结构的。当然,在Jface里面是有一个TreeNode的,org.eclipse.jface.viewers.TreeNode,相应的还提供了一个org.eclipse.jface.viewers.TreeNodeContentProvider。
ContentProvider代码:
构建setInput的模型
就是在构建模型的时候,将所有的子模型都加载好了:
其他代码:
二. Lazy Load模式(简单)
在setInput的模型中,只有最顶层的模型,再每次点击+的时间,将下一层的模型动态的载入,从而将树的子节点构造出来。也就是在getChildren中动态载入即可。
ContentProvider代码。
注意getChildren 和hasChildren的方法实现,hasChildren返回true,表示需要给这个树节点显示+号。点击+号,getChildren会动态的载入子节点数据,这样就实现了Lazy Load了。
构建setInput的模型:
只需要构建第一层树节点即可,后面的就交给ContentProvider去处理。
其他代码:
三. Lazy Loader模式(显示Pending)
和模式是二一样的,都是点+载入子模型。但是,如果是需要长时间的加载,模式二会将界面卡住,而这个模式,再点击+号后,会先显示一个Pending树节点(并可以显示进度条),并看到随着数据一个一个载入树节点一个一个添加出来,所有数据都载入后,Pending树节点消失,这样用户体验就会好很多。在这个模式,需要用到很多其他的类,具体看代码:
模型代码:
1. 需要实现IDeferredWorkbenchAdapter接口。
2. 注意fetchDeferredChildren方法。将载入子数据的过程放到了模型里面(很怪)。
ContentProvider代码。
1. 添加了一个DeferredTreeContentManager,并使用该manager代理getChildren方法。
2. hasChildren返回true。
3. 修改了getElements方法。
LabelProvider代码:
1. 修改了getText方法。由于我们说中间会创建一个显示Pending的节点,这个节点就是PendingUpdateAdapter,需要特别指定显示的text。
构建setInput的模型:
1. 只需要预先放入根节点即可。子节点的载入就依赖于点击+号,lazy载入了。
其他代码:
四. 总结
1. 简单模式适合于你一次性将数据全部载入,而后在setInput一次显示出来。
2. Lazy Load模式(简单)适合于性能影响不大的点击+号Lazy的载入数据。
3. Lazy Load模式(显示Pending)适合于载入过程比较长,为了提供用户交互而使用
4. Lazy Load模式都存在着遍历的问题。因为有的模型的子节点还没有完全载入,而你却依赖所有这些子节点的时候,这时就必须在代码里面将所有子节点打开,让其载入所有子数据至最后一层,对于(简单)和(显示Pending)都可以这么去做。
5. 还是4的情况,由于(显示Pending)是异步载入的,需要更复杂的判断,并基于线程去判断某节点是否载入完毕,等你自己去实现的时候,你会发现这是有多复杂的^-^
五. 其他相关的类
org.eclipse.jface.viewers.TreeNode
org.eclipse.jface.viewers.TreeNodeContentProvider
org.eclipse.jface.viewers.ArrayContentProvider
org.eclipse.ui.progress.IDeferredWorkbenchAdapter
org.eclipse.ui.progress.DeferredTreeContentManager
载入完毕,Pending消失。
我们先从基础的说起,先来看ITreeContentProvider 接口:
- public interface ITreeContentProvider {
- public Object[] getElements(Object inputElement) ;
- public Object[] getChildren(Object parentElement) ;
- public boolean hasChildren(Object element) ;
- // ...
- }
getElements 表示在setInput(Object)的时候,如何从Object中得到一个数组,而使用这个数组去将树的第一层结点显示出来。这个方法只在setInput时才使用一次。
getChildren表示在每次展开树的节点时,如果得到下一级节点的值,当然,树的节点展开了一次就不会再调用这个方法了,因为在树节点对应的控件TreeItem中,已经创建好了子节点控件了。
hasChildren就是判断当前节点是否有子节点,有的话,就显示+号。
ITreeContentProvider的使用类型可以分成3种(我自己分的,^-^)。
1。简单模式
2。Lazy Loader模式(简单)
3。Lazy Loader模式(显示Pending)
一. 简单模式
其实就是在setInput的模型中,已经预先将所有的子模型都载入完毕,而不用再动态的载入子模型了。
模型说明:
这个模型代表树节点,是支持父子结构的。当然,在Jface里面是有一个TreeNode的,org.eclipse.jface.viewers.TreeNode,相应的还提供了一个org.eclipse.jface.viewers.TreeNodeContentProvider。
- public class TreeNode {
- private TreeNode parent;
- private List<TreeNode> children = new ArrayList<TreeNode>();
- private Object value;
ContentProvider代码:
- public class SimpleContentProvider implements ITreeContentProvider {
- public Object[] getElements(Object inputElement) {
- return ((TreeNode) inputElement).getChildren().toArray();
- }
- public Object[] getChildren(Object parentElement) {
- return ((TreeNode) parentElement).getChildren().toArray();
- }
- public boolean hasChildren(Object element) {
- return ((TreeNode) element).getChildren().size() > 0;
- }
构建setInput的模型
就是在构建模型的时候,将所有的子模型都加载好了:
- private TreeNode buildLazyContent() {
- TreeNode root = new TreeNode(null);
- TreeNode level_1_1 = new TreeNode("1.1");
- root.addChild(level_1_1);
- // ...
- return root;
- }
其他代码:
- viewer.setLabelProvider(new TreeViewerLabelProvider());
- viewer.setContentProvider(new SimpleContentProvider());
- viewer.setInput(this.buildSimpleContent());
二. Lazy Load模式(简单)
在setInput的模型中,只有最顶层的模型,再每次点击+的时间,将下一层的模型动态的载入,从而将树的子节点构造出来。也就是在getChildren中动态载入即可。
ContentProvider代码。
注意getChildren 和hasChildren的方法实现,hasChildren返回true,表示需要给这个树节点显示+号。点击+号,getChildren会动态的载入子节点数据,这样就实现了Lazy Load了。
- public class SimpleLazyContentProvider implements ITreeContentProvider {
- public Object[] getChildren(Object parentElement) {
- TreeNode parent = (TreeNode) parentElement;
- this.loadChildren(parent);
- return parent.getChildren().toArray();
- }
- public boolean hasChildren(Object element) {
- return true;
- }
- private void loadChildren(TreeNode parent) {
- TreeNode child_1 = new TreeNode("1");
- parent.addChild(child_1);
- TreeNode child_2 = new TreeNode("2");
- parent.addChild(child_2);
- }
构建setInput的模型:
只需要构建第一层树节点即可,后面的就交给ContentProvider去处理。
- private TreeNode buildSimpleLazyContent() {
- TreeNode root = new TreeNode(null);
- TreeNode level_1_1 = new TreeNode("1.1");
- root.addChild(level_1_1);
- return root;
- }
其他代码:
- viewer.setLabelProvider(new TreeViewerLabelProvider());
- viewer.setContentProvider(new SimpleLazyContentProvider());
- viewer.setInput(this.buildSimpleLazyContent());
三. Lazy Loader模式(显示Pending)
和模式是二一样的,都是点+载入子模型。但是,如果是需要长时间的加载,模式二会将界面卡住,而这个模式,再点击+号后,会先显示一个Pending树节点(并可以显示进度条),并看到随着数据一个一个载入树节点一个一个添加出来,所有数据都载入后,Pending树节点消失,这样用户体验就会好很多。在这个模式,需要用到很多其他的类,具体看代码:
模型代码:
1. 需要实现IDeferredWorkbenchAdapter接口。
2. 注意fetchDeferredChildren方法。将载入子数据的过程放到了模型里面(很怪)。
- public class PendingTreeNode extends TreeNode implements IDeferredWorkbenchAdapter {
- public void fetchDeferredChildren(Object object, IElementCollector collector,
- IProgressMonitor monitor) {
- PendingTreeNode parent = (PendingTreeNode) object;
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- PendingTreeNode node1 = new PendingTreeNode("1");
- parent.addChild(node1);
- collector.add(node1, monitor);
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- PendingTreeNode node2 = new PendingTreeNode("2");
- parent.addChild(node2);
- collector.add(node2, monitor);
- }
ContentProvider代码。
1. 添加了一个DeferredTreeContentManager,并使用该manager代理getChildren方法。
2. hasChildren返回true。
3. 修改了getElements方法。
- public class PendingLazyContentProvider implements ITreeContentProvider {
- private DeferredTreeContentManager manager;
- public Object[] getChildren(Object parentElement) {
- return manager.getChildren(parentElement);
- }
- public boolean hasChildren(Object element) {
- return true;
- }
- public Object[] getElements(Object inputElement) {
- if (inputElement instanceof PendingTreeNode) {
- return ((PendingTreeNode) inputElement).getChildren().toArray();
- }
- return new Object[0];
- }
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- if (manager == null) {
- manager = new DeferredTreeContentManager(this, (TreeViewer) viewer);
- }
- }
- }
LabelProvider代码:
1. 修改了getText方法。由于我们说中间会创建一个显示Pending的节点,这个节点就是PendingUpdateAdapter,需要特别指定显示的text。
- public class PendingTreeViewerLabelProvider extends LabelProvider {
- public String getText(Object obj) {
- if (obj instanceof TreeNode) {
- return ((TreeNode) obj).getValue().toString();
- } else if (obj instanceof PendingUpdateAdapter) {
- return ((PendingUpdateAdapter) obj).getLabel(null);
- }
- return obj.toString();
- }
构建setInput的模型:
1. 只需要预先放入根节点即可。子节点的载入就依赖于点击+号,lazy载入了。
- private PendingTreeNode buildPendingLazyContent() {
- PendingTreeNode root = new PendingTreeNode(null);
- PendingTreeNode level_1_1 = new PendingTreeNode("1.1");
- root.addChild(level_1_1);
- return root;
- }
其他代码:
- viewer.setLabelProvider(new PendingTreeViewerLabelProvider());
- viewer.setContentProvider(new PendingLazyContentProvider());
- viewer.setInput(this.buildPendingLazyContent());
四. 总结
1. 简单模式适合于你一次性将数据全部载入,而后在setInput一次显示出来。
2. Lazy Load模式(简单)适合于性能影响不大的点击+号Lazy的载入数据。
3. Lazy Load模式(显示Pending)适合于载入过程比较长,为了提供用户交互而使用
4. Lazy Load模式都存在着遍历的问题。因为有的模型的子节点还没有完全载入,而你却依赖所有这些子节点的时候,这时就必须在代码里面将所有子节点打开,让其载入所有子数据至最后一层,对于(简单)和(显示Pending)都可以这么去做。
5. 还是4的情况,由于(显示Pending)是异步载入的,需要更复杂的判断,并基于线程去判断某节点是否载入完毕,等你自己去实现的时候,你会发现这是有多复杂的^-^
五. 其他相关的类
org.eclipse.jface.viewers.TreeNode
org.eclipse.jface.viewers.TreeNodeContentProvider
org.eclipse.jface.viewers.ArrayContentProvider
org.eclipse.ui.progress.IDeferredWorkbenchAdapter
org.eclipse.ui.progress.DeferredTreeContentManager