JFace TreeViewer使用

    技术2022-05-19  18

    简介

           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());

                  }

               }

    参考文献

    1.         http://www.eclipse.org/articles/Article-TreeViewer/TreeViewerArticle.htm


    最新回复(0)