Eclipse插件开发之TreeViewer

contentprovider在插件开发和RCP(Rich Client Platform)开发中常常被用到,譬如你要创建一个TreeViewer(树形控件)就需要一个ITreeContentProvider,如果要实现一个TableViewer(表控件)就需要一个IStructuredContentProvider,contentprovider主要的作用就是返回当前界面中的数据。

1.内容提供器(ITreeContentProvider)

TreeViewer的内容提供器(ITreeContentProvider)构建树中比较复杂的部分,它为树的显示提供了内容,内容提供器要实现的方法如下。

(1)getElements。

此函数定义为“public Object[] getElements(Object inputElement);”,当程序开始构建树时,首先调用getElements返回一个对象的数组,此数组对象表示当前树的根节点,inputElement参数为TreeViewer的输入(setInput的输入数据)。

(2)hasChildren。

此函数定义为“public boolean hasChildren(Object element);”,当TreeViewer显示一个节点后,会调用hasChildren函数判断当前节点是否有子节点,如果有子节点则显示“+”,element参数为要判断是否有子节点的节点。

(3)getChildren。

此函数定义为“public Object[] getChildren(Object parentElement);”,当用户选择节点打开子节点时,会调用getChildren函数返回下一层子节点,parentElement参数为选择的节点。

(4)getParent。

此函数定义为“public Object getParent(Object element);”,可以通过此方法返回element的父节点。

(5)inputChanged。

此函数定义为“public void inputChanged(Viewer viewer, Object oldInput, Object newInput);”,当输入改变时调用此方法。

(6)dispose。

此函数定义为“public void dispose();”,当树销毁时被调用。

其中,getElements、hasChildren和getChildren是常用的方法,用户通过重写这几种方法构建一棵树,过程如下:通过getElements方法得到根,再通过hasChildren判断根下是否有子节点,如果有子节点,可以通过getChildren得到所有的子节点。如例程15-2为ITreeContentProvider接口的一个简单实现。

例程15-2  FileTreeContentProvider.java


  
  
  1. class FileTreeContentProvider implements ITreeContentProvider {
  2. public Object[] getChildren(Object arg0) {
  3. //返回树的下一级节点
  4. return ((File) arg0).listFiles();
  5. }
  6. public Object getParent(Object arg0) {
  7. //返回树的上一级节点
  8. return ((File) arg0).getParentFile();
  9. }
  10. public boolean hasChildren(Object arg0) {
  11. Object[] obj = getChildren(arg0);
  12. //判断树是否有下一级节点,true为在节点显示"+"信息
  13. return obj == null ? false : obj.length > 0;
  14. }
  15. public Object[] getElements(Object arg0) {
  16. //打印出树的输入信息,通常用户可以通过输入信息构建树
  17. System.out.println(arg0);
  18. // File.listRoots()作为树的根节点
  19. return File.listRoots();
  20. }
上例内容提供器通过文件系统获得树的输入内容,从而使用户构造的树能显示磁盘文件的树结构。

2.标签提供器(ILabelProvider)

在TreeViewer中,通过标签提供器(ILabelProvider)来显示节点的相关信息,包括显示内容和图标。

ILabelProvider主要实现getImage和getText函数。当TreeViewer得到一个节点后会通过getText得到此节点的显示文本,通过getImage方法得到节点的显示图标,代码如例程15-3所示。


  
  
  1. class ViewLabelProvider extends ILabelProvider{
  2. public String getText(Object obj) {
  3. return obj.toString();
  4. }
  5. public Image getImage(Object obj) {
  6. String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
  7. if (obj instanceof TreeParent)
  8. imageKey = ISharedImages.IMG_OBJ_FOLDER;
  9. return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
  10. }
  11. }
3.标签器还比较简单,在TreeViewer中最主要和最复杂的是内容器,熟悉内容器是掌握TreeViewer的要点。

TreeViewer内容器的代码如下:


  
  
  1. //内容器。由它决定哪些对象记录应该输出在TreeViewer里显示
  2. public class TreeViewerContentProvider implements ITreeContentProvider {
  3. // 由此方法决定树的“第一级”结点显示哪些对象。inputElement是用tv.setInput()方法
  4. //输入的那个对象。Object[]是一个数组,数组中一个元素就是一个结点
  5. public Object[] getElements(Object inputElement) {
  6. if (inputElement instanceof List) {
  7. List input = (List) inputElement;
  8. return input.toArray();
  9. }
  10. return new Object[ 0]; // 空数组
  11. }
  12. // 判断参数element结点是否有子结点
  13. // 返回true表示element有子结点,则其前面会显示有“+”号图标
  14. public boolean hasChildren(Object element) {
  15. ITreeEntry entry = (ITreeEntry) element;
  16. List list = entry.getChildren();
  17. return !(list == null || list.isEmpty()); // 判断list是否有子结点
  18. }
  19. // 当界面中单击某结点时,由此方法决定被单击结点应该显示哪些子结点
  20. // parentElement就是被单击的结点对象。返回的数组就是应显示的子结点
  21. public Object[] getChildren(Object parentElement) {
  22. ITreeEntry entry = (ITreeEntry) parentElement;
  23. List list = entry.getChildren();
  24. //虽然通过界面单击方式,有子结点才会执行到此方法,但仍然要做非空判断,
  25. //因为在调用TreeViewer的某些方法时其内部会附带调用此方法
  26. if (list == null) return new Object[ 0];
  27. return list.toArray();
  28. }
  29. // --------------以下方法暂时无用,空实现----------------
  30. public void dispose() {} //树被销毁时触发
  31. public void inputChanged(Viewer v,Object oldInput, Object newInput){} //每次tv.setInput触发
  32. public Object getParent(Object element) { return null;} //取得element的父结点。极少使用
  33. }

程序说明:在内容器中最关键的是getElements、hasChildren、getChildren这3个方法。

getElements只在显示“第一级”结点时才会被执行。

hasChildren主要用于判断当前所显示的结点是否有子结点,如果有子结点则前面显示一个“+”号图标,而有“+”号的结点则可以单击展开其下一级的子结点。

当单击有“子”的结点时,才会执行getChildren方法。展开其子结点后,又会对子结点执行一遍hasChildren方法,以决定其各子结点前是否显示“+”图标。

图15.4给出了内容器在启动、单击结点、关闭窗口这3种情况时的方法执行的时序图。

下面以本实例来解释此图:

树界面启动时:先执行inputChanged方法。接着执行getElements方法,其inputElement参数就是由setInput传入的对象:包含所有实体对象的List。此List在getElements中被转化成一个数组,数组包含第一级结点的两个元素中国和美国,它们将首先显示在界面上。接下来执行两次hasChildren方法,判断中国和美国是否有子结点。它们都有子结点,故方法返回True,两结点前都显示“+”图标。

单击有子结点的中国:先执行一次getChildren方法,方法的parentElement参数就是中国结点对象。方法中把中国的子结点取出并转化成一个数组返回,此数组包含3个元素“北京、台湾、桂林”。接下来连续执行3次hasChildren方法来判断“北京、台湾、桂林”是否有子结点,如果有,则在结点前显示一个“+”图标。

单击没有子结点的桂林:不会执行内容器中的任何方法。

关闭窗口:会先后执行inputChanged和dispose方法。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值