JFace TreeViewer使用 及内容提供器(IStructuredContentProvider)

时间:2023-01-20 19:38:34

内容提供器(IStructuredContentProvider)

TableViewer中的内容管理器比较简单,用户可以通过实现getElements返回表格的所有数据。

getElements定义为“public Object[] getElements(Object inputElement)”,返回Object[]对象数组,其中数组中每一个对象代表表格的一列。当TableViewer输入数据后,内容管理器将根据输入数据构造表格对象数据,如下代码所示。

public Object[] getElements(Object inputElement) {

//通过输入的数据建表
Vector v = (Vector) inputElement;
return v.toArray();
}

其中,输入数据inputElement为Vector类型的变量,通过“v.toArray();”返回对象数组。

简介
JFace 是一个 UI 工具类集,用于处理许多通用 UI 编程任务。 JFace 无论是从 API 或其实现都是 Window-System- Independent (视窗系统无关)的,设计与 SWT 共同工作而并非完全替代。 JFace 是基于 SWT 的 Java 应用程序框架。其目标是提供一组可重用的组件,来简化以 Java 实现的 GUI 程序的编写。虽然 JFace 与 Eclipse 运行时核心有一些联系 ,但是提取 JFace 和 SWT 使用到非基于 Eclipse 运行时的独立 Java 程序还是相当直截了当的。

   使用 JFace 开发 UI 程序必须使用 Eclipse PDE (Plug-in Development Environment) 支持,开发程序必须导入依赖的类库包括:
org.eclipse.core.commands_<version info>.jar

org.eclipse.equinox.commands_<version info>.jar

org.eclipse.osgi_<version info>.jar

org.eclipse.jface_<version info>.jar

org.eclipse.swt.win32.win32.x86_<version info>.jar

org.eclipse.ui.workbench_<version info>.jar
   其中 org.eclipse.ui.workbench 并非 JFace 必须的类库,但其中包含很多有用的 Dialog ,一般添加。

TreeViewer 类
JFace 中提供了 TreeViewer 组件,用 TreeViewer 来表示树型结构对象的显示。 TreeViewer 功能比较强,它能定义节点、节点的显示标签、显示图标以及响应事件等信息。

java.lang.Object

  org.eclipse.jface.viewers.Viewer

      org.eclipse.jface.viewers.ContentViewer

          org.eclipse.jface.viewers.StructuredViewer

              org.eclipse.jface.viewers.ColumnViewer

                  org.eclipse.jface.viewers.AbstractTreeViewer

                      org.eclipse.jface.viewers.TreeViewer
   TreeViewer 类主要通过内容提供器( ITreeContentProvider )和标签提供器( ILabelProvider )组织树节点的内容和显示的信息。 TreeViewer 通过 setContentProvider 方法设置内容提供器,这个方法继承自 AbstractTreeViewer ,通过 setLabelProvider 方法设置标签提供器,这个方法继承自 ColumnViewer 。 TreeViewer 类的使用主要围绕内容和标签提供器两个类来进行。



   TreeViewer 的构建步骤如下:
  1. 创建 TreeViewer 对象;

  2. 设定内容管理器 setContentProvider ;

  3. 设定标签提供器 setLabelProvider ;

  4. 设定 TreeViewer 的输入数据 setInput ;

ITreeContentProvider 接口
继承关系:

IContentProvider

IStructuredContentProvider

org.eclipse.jface.viewers.ITreeContentProvider

方法摘要

Object []

getChildren (Object parentElement)
Returns the child elements of the given parent element.

Object

getParent (Object element)
Returns the parent for the given element, or null indicating that the parent can’t be computed.

boolean

hasChildren (Object element)
Returns whether the given element has children.

从接口 org.eclipse.jface.viewers.IStructuredContentProvider 继承的方法

getElements

从接口 org.eclipse.jface.viewers.IContentProvider 继承的方法

dispose , inputChanged

   ITreeContentProvider 为树的显示提供了内容,通过 getElements 方法得到树根,再通过 hasChildren 判断根下是否有子节点,如果有子节点,可以通过 getChildren 得到所有的子节点。

ILabelProvider 接口
继承关系:

org.eclipse.jface.viewers.IBaseLabelProvider

org.eclipse.jface.viewers.ILabelProvider

方法摘要

Image

getImage (Object element)
Returns the image for the label of the given element.

String

getText (Object element)
Returns the text for the label of the given element.

从接口 org.eclipse.jface.viewers.IBaseLabelProvider 继承的方法

addListener , dispose , isLabelProperty , removeListener

   ILabelProvider 主要实现 getImage 和 getText 函数,当 TreeViewer 得到一个节点后会通过 getText 得到此节点的显示文本,通过 getImage 方法得到节点的显示图标。

TreeViewer 例程
设计框架
设计一个实验管理目录的 TreeViewer ,模型结构如下:

包括下列类的层次结构:

          树根

                 用户(名称,用户目录)

                        样品

                               实验

                                      处理

树根下可以有多个用户,每个用户下可以有多个样品,每个样品下可以有多个实验,每个实验中可以包括多个实验数据的处理结果,根据这种组织模式,我们来创建类。

   首先,创建一个基本的 Hello RCP 程序(不带 Activator ,即不勾选创建 RCP 过程中的 Activator 选项)。在 plugin.xml 中创建一个新的 org.eclipse.ui.views 扩展点,并新建一个 view ,命名其类名称为 cn.eclipsercp.jface.treeviewer.test.ViewPart1 ,继承自 org.eclipse.ui.part.ViewPart ,增加成员变量 ID=” “ cn.eclipsercp.jface.treeviewer.test.ViewPart1” , 然后修改 Perpective 代码如下:

public void createInitialLayout(IPageLayout layout) {

   layout.setEditorAreaVisible( false );

   layout.addView(ViewPart1. ID , SWT. LEFT , 1.0f, layout.getEditorArea());

}

运行程序:

模型实现

   设计所有树上节点的基类 Node 如下:
public class Node {

    String name ;

    Node parent ;

    List<Node> children = new ArrayList<Node>(10);



    Node() {}



    Node(Node parent) {

       this .setParent(parent);

    }



    public String getName() {

       return name ;

    }



    public void setName(String name) {

       this . name = name;

    }



    public Node getParent() {

       return parent ;

    }



    public void setParent(Node parent) {

       this . parent = parent;

    }



    public void addChild(Node child) {

       child.setParent( this );

       children .add(child);

    }



    public void removeChild(Node child) {

       children .remove(child);

    }



    public List<Node> getChildren() {

       return children ;

    }

}

主要包括 parent , children 和 Name 等私有成员变量,以及访问的 setter 和 getter 方法,通过一个 List 来保存该 Node 的所有子节点。

   然后分别在此类的基础上继承得到 User (用户), Sample (样品), Experiment (实验), Process (处理)等类型,为了简单,这些类只是继承 Node 类即可,最后定义一个单例模式的 RootNode :

public class RootNode extends Node {

private static RootNode root = null ;



private RootNode() {}



public static synchronized RootNode getRootNode() {

   if ( root == null ) {

       root = new RootNode();

       root .setParent( null );



       root .initRootNode();

   }



   return root ;

}



private void initRootNode() {

   User user;

   Sample sample1,sample2;

   Experiment expr1,expr2;

   Process proc1,proc2;



   user = new User();

   user.setName( "Zhang" );

   root .addChild(user);



   user = new User();

   user.setName( "Yang" );

   sample1 = new Sample();

   sample1.setName( "Sample1" );

   sample2 = new Sample();

   sample2.setName( "Sample2" );

   user.addChild(sample1);

   user.addChild(sample2);



   expr1 = new Experiment();

   expr1.setName( "Exp1" );

   expr2 = new Experiment();

   expr1.setName( "Exp2" );



   sample2.addChild(expr1);

   sample2.addChild(expr2);



   proc1 = new Process();

   proc2 = new Process();

   proc1.setName( "Proc1" );

   proc2.setName( "Proc2" );



   expr2.addChild(proc1);

   expr2.addChild(proc2);



   root .addChild(user);



   user = new User();

   user.setName( "Wang" );

   root .addChild(user);    

}

}

连接模型与 TreeViewer
模型与 TreeViewer 之间进行连接主要是依靠 ContentProvider 和 LabelProvider 两个接口,分别通过两个类实现这些接口中的方法,然后在 ViewPart1 的 CreateControl 方法中创建 TreeViwer ,并设置他的内容提供器和标签提供器:

public class ViewPart1 extends ViewPart {

public static final String ID = "cn.eclipsercp.jface.treeviewer.test.ViewPart1" ;

Node root ;

TreeViewer tv ;



public ViewPart1() {

   // TODO Auto-generated constructor stub

}



@Override

public void createPartControl(Composite parent) {

       FillLayout fillLayout = new FillLayout(SWT. VERTICAL );

       parent.setLayout(fillLayout);



       tv = new TreeViewer(parent);

       tv .setContentProvider( new TVContentProvider());

       tv .setLabelProvider( new TVLabelProvider());

       root = RootNode.getRootNode ();

       tv .setInput( root );

   }



@Override

public void setFocus() {

   // TODO Auto-generated method stub

}

}

内容提供器:

public class TVContentProvider implements ITreeContentProvider {

@Override

public Object[] getChildren(Object parentElement) {

return ((Node) parentElement).getChildren().toArray();

}

@Override

public Object getParent(Object element) {

return ((Node) element).getParent();

}

@Override

public boolean hasChildren(Object element) {

return (((Node) element).getChildren().size() > 0);

}

@Override

public Object[] getElements(Object inputElement) {

return ((Node) inputElement).getChildren().toArray();

}

@Override

public void dispose() {

// TODO Auto-generated method stub

}

@Override

public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

// TODO Auto-generated method stub

}

}

标签提供器:

public class TVLabelProvider implements ILabelProvider {

    private Map<ImageDescriptor, Image> imageCache = new HashMap<ImageDescriptor, Image>(20);



    @Override

    public Image getImage(Object element) {

       ImageDescriptor descriptor = null ;

       if (element instanceof User) {

           descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (

                    Application. ID , "icons/alt_window_16.gif" );

       } else if (element instanceof Sample) {

           descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (

                  Application. ID , "icons/alt_window_16.gif" );

       } else if (element instanceof Experiment) {

           descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (

                  Application. ID , "icons/alt_window_16.gif" );

       } else if (element instanceof cn.eclipsercp.jface.treeviewer.test.model.Process) {

           descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (

                  Application. ID , "icons/alt_window_16.gif" );

       }

       else {

           throw unknownElement(element);

       }



       //obtain the cached image corresponding to the descriptor

       Image image = (Image) imageCache .get(descriptor);

       if (image == null ) {

           image = descriptor.createImage();

           imageCache .put(descriptor, image);

       }



       return image;

    }



    @Override

    public String getText(Object element) {

       String text;

       if (element instanceof RootNode)

           text= "root" ;

       else   if (element instanceof User)

           text=((User)element).getName();

       else if (element instanceof Sample)

           text=((Sample)element).getName();

       else if (element instanceof Experiment)

           text=((Experiment)element).getName();

       else if (element instanceof cn.eclipsercp.jface.treeviewer.test.model.Process)

           text=((cn.eclipsercp.jface.treeviewer.test.model.Process)element).getName();

       else

           text=((Node)element).getName();



       return text;

    }



    @Override

    public void addListener(ILabelProviderListener listener) {

       // TODO Auto-generated method stub



    }



    @Override

    public void dispose() {

       // TODO Auto-generated method stub



    }



    @Override

    public boolean isLabelProperty(Object element, String property) {

       // TODO Auto-generated method stub

       return false ;

    }



    @Override

    public void removeListener(ILabelProviderListener listener) {

       // TODO Auto-generated method stub



    }



    protected RuntimeException unknownElement(Object element) {

       return new RuntimeException( "Unknown type of element in tree of type " + element.getClass().getName());

    }

}

运行程序:

添加选择事件
在 ViewPart1 的 CreateControl 方法中,为 TreeViewer 成员变量 tv 增加选中节点的事件,通过 System.out.println 输出来表达事件的行为:

 tv .addSelectionChangedListener( new ISelectionChangedListener() {

           public void selectionChanged(SelectionChangedEvent event) {

              // if the selection is empty clear the label

              if (event.getSelection().isEmpty()) {

                  System. out .println( "Selected Nothing" );

                  return ;

              }

              if (event.getSelection() instanceof IStructuredSelection) {

                  IStructuredSelection selection = (IStructuredSelection) event

                         .getSelection();

                  StringBuffer selected = new StringBuffer();

                  for (Iterator iterator = selection.iterator(); iterator

                         .hasNext();) {

                     Object element = (Node) iterator.next();

                     String value = ((Node)element).getName();

                     selected.append(value);

                     selected.append( ", " );

                  }

                  // remove the trailing comma space pair

                  if (selected.length() > 0) {

                     selected.setLength(selected.length() - 2);

                  }



                  System. out .println(selected.toString());

              }

           }