Eclipse RCP中Viewer交互的三种方式/Make your Eclipse applications richer with view linking

摘要:
本文将介绍Eclipse中的View如何与其他View进行交互的三种方式,并分析在不同的情况下这几种方式的优劣。View应该具备识别和使用UISelection事件对象的能力。Workbenchpage实现了rg.eclipse.ui.ISelectionService接口定义的service,将UISelection事件发送到监听器中。Eclipse中的每一个UIView都通过org.eclipse.ui.IWorkbenchPartSite与workbenchsite相关联。Selectionprovider是在workbenchsite中注册的。注册后在view中的tableviewer的UIselection变化将被相应的监听器获得。一个View仅仅需要在其中使用JFaceViewer并将其注册为selectionprovider即可实现选择事件的发布。3View需要监听一个不包含JFaceviewer对象的View。

简介

Eclipse平台的插件机制可以使用户方便的创建GUI程序。例如,插件可以给GUI提供Views(查看器)。这些UI的View需要和其他组件关联才能真正发挥发挥作用,否则将形成“孤岛”。

以下图所示的一个旅游景点介绍的GUI应用程序为例,这个GUI程序将景点列表View和景点介绍View关联在一起,当在景点列表View中选择不同的旅游景点时,景点介绍View会显示相应的介绍。

Eclipse RCP中Viewer交互的三种方式/Make your Eclipse applications richer with view linking第1张

本文将介绍Eclipse中的View如何与其他View进行交互的三种方式,并分析在不同的情况下这几种方式的优劣。Eclipse开发人员可以使用下面这三种方式来关联View

1“选择提供者--选择监听者”模式。

2结合一些事件(Events)使用IAdapatble接口

3属性变化监听器,它可以在属性变化事将事件推送(Push)到注册的监听器中。

选择提供者--选择监听者”模式

“选择提供者--选择监听者”模式可以使一个View来响应其他View的变化。例如,当用户点击景点列表View的一个城市名时,其他view想获得这个悬着事件并作出响应。这些VIew需要UISelection对象中的信息(比如表示城市名称的一个String)并使用这些信息来从模型中获取其他相关信息

View应该具备识别和使用UISelection事件对象的能力。org.eclipse.ui.ISelectionListener是一个用于监听UI选择事件的监听器接口。选择事件监听器必须在workbenchpage中注册。Workbenchpage实现rg.eclipse.ui.ISelectionService接口定义的service,将UISelection事件发送到监听器中。选择事件监听器必须和一个选择服务一起注册。

能被选择的UIView具备发布UIselection事件的能力,view可以通过在他们各自的workbenchsite中注册“selectionprovider”来实现这一点。Eclipse中的每一个UIView都通过org.eclipse.ui.IWorkbenchPartSiteworkbenchsite相关联。Selectionprovider是在workbenchsite中注册的。

views使用“选择提供者--选择监听者”模式关联起来之后,一个viewworkbenchpage中注册为监听器,其他的view若要发布selection事件,则需在各自的workbenchsite中注册为selectionproviderorg.eclipse.ui.ISelectionListener接口签名如下所示:

	public void selectionChanged(IWorkbenchPart part, ISelection selection);

若要使一个view可以监听选择变化事件,此View必须实现ISelectionListener接口并在workbench中进行注册,如下面的代码所示:

public class MyView extends ViewPart implements  ISelectionListener{
    public void createPartControl(Composite parent) {
        // add this view as a selection listener to the workbench page
        getSite().getPage().addSelectionListener((ISelectionListener) this);
}
    // Implement the method defined in ISelectionListener, to consume UI selections
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        //Examine selection and act on it!
    }
}

更好的方式是指定所监听的View,只需将目标ViewID作为第一个参数传递过去就可以实现,如下所示:

getSite().getPage().addSelectionListener("SampleViewId",(ISelectionListener)this);

下面的代码展示了如何将一个view中的tableviewer注册为workbenchsite中的selectionprovider。注册后在view中的tableviewerUIselection变化将被相应的监听器获得。

public void createPartControl(Composite parent) {
    // Set up a JFace Viewer
    viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
    viewer.setContentProvider(new ViewContentProvider());
    viewer.setLabelProvider(new ViewLabelProvider());
    viewer.setSorter(new NameSorter());
    viewer.setInput(getViewSite());
  
    // ADD the JFace Viewer as a Selection Provider to the View site.
    getSite().setSelectionProvider(viewer);
}

这个view将它创建的TableViewer注册为selectionprovider是因为:

1这个view将使用tableviewer来显示信息,用户将与TableViewer交互

2TableViewer实现了selectionprovider接口,可以将选择事件发布到workbenchpartsite中。

JFaceviewer都是选择事件提供者,因此您在使用它们时不需要创建一个选择事件提供者。一个View仅仅需要在其中使用JFaceViewer并将其注册为selectionprovider即可实现选择事件的发布。

我们需要不同的关联方法

尽管“选择提供者--选择监听者”模式使用方便并且能满足大多数的需求,但由于以下原因,我们仍需要一种不同的方式来关联视图:

1信息量超过了UIselection对象的承载力。

2View需要发布处理后的信息而不仅仅是选择对象信息。

3View需要监听一个不包含JFaceviewer对象的View

您可以使用org.eclipse.core.runtime.IAdaptable接口来解决第一个问题,这个接口可以使一个选择事件对象承载更多的信息。需求23则需要程序员做更多的工作,也许“属性变化监听器模式”更适用于那种需求。

使用IAdaptable接口

实现IAdaptable接口的类可以动态地根据需求返回不同适配器,这些适配器可以用来获取更多的信息。若一个viewer中的selection对象实现了IAdaptable接口,那么它可以使用不同类适配器来提供更多信息。org.eclipse.core.runtime.IAdaptable接口的签名如下:

public void object getAdapter(Class adapter);

很明显,调用者应该知道自己所需要的适配器类型。例如一个以单层树的形式来提供城市列表的TableViewer,其中表示城市的类为CityClass。CityClass对象应该包含一些有关这个城市的基本信息,并只有在需要的时候才返回详细的信息。在下面的代码中,CityClass实现了不同类型的适配器,从而可以根据需要来提供不同的信息。

class CityClass implements IAdaptable { 
      private String cityName;

      public CityClass(String name) {   
            this.name = name;
      }
      public String getName() {
        return name;
      }
      public CityClass getParent() {
            return parent;
      }
      public String toString() {
            return getName();
      } 

      public Object getAdapter(Class key) {
        if (key.getName().equals("ITransportationInfo"))
          return CityPlugin.getInstance().getTransportAdapter();
        else (key.getName().equals("IPlacesInfo"))
          return CityPlugin.getInstance().getPlacesAdapter();
        return null;
      }
}

熟悉EclipseIDE开发者应该了解其中的OutlineView,这个View显示了在editor中打开的文件的结构。OutlineView这个例子展示了通过使用IAdaptable接口和一些特定的事件类型,如何根据其他view的内容来初始化一个view。一个editor必须为打开的文件创建一个Outlinepage,这个内容OutlinepageIContentOutlinePage接口相关。Editor实现IAdaptable接口之后,便可以提供相关的适配器来作为IContentOutlinePage来使用。

另一个IAdaptable的例子是PropertiesViewPropertiesView追踪活跃的part并在当前选择对象上调用getAdapter()方法。所需的适配器类型为IPropertySourcePropertiesView从而可以使用IPropertySource适配器来获取属性信息并显示。

在这些视图关联的例子中,应用程序在发生SelectionchangePartActivation通知时通过IAdaptable接口来获取信息。因此,如果selectionIAdaptable的,用户可以通过适配器来获取更多的信息。

属性变化监听器模式

您可以使用“属性变化监听器模式”来解决前面所说的第23个问题:一个View如何从一个非UIview中获取信息,以及一个View如何发布在选择事件发生后经过处理后的信息。

您可以创建一个插件来接受注册属性变化监听器的注册,并在需要时通知所注册的插件。应用程序可以创建选择事件并通知监听器,从而使ViewUIView中获取信息。与selectionprovider不同,propertychangeprovider并不需要实现某个特定的接口。你必须自己定义注册的监听器和创建的provider的语义。下面的代码显示了如何在propertyproviderview或插件中添加或删除propertychange监听器。


//To add a listener for property changes to this notifier:
  public void addPropertyChangeListener(IPropertyChangeListener listener);
//To remove the given content change listener from this notifier:
  public void removePropertyChangeListener(IPropertyChangeListener listener);

Propertyprovider将使用org.eclipse.jface.util.PropertyChangeEvent来创建一个可以发布的Event。同时,使用者将维护一个监听器列表,并对propertyprovider提供回调功能。例如,一个每隔一小时从世界气候服务获取城市气象信息的插件,希望将这些气象信息与其他View分享。CityWeatherPlugin可以暴露一个名为CitiesWeatherXML的服务,需要这些信息的view则将作为PropertyChange监听器注册到CityWeatherPlugin中。为了实现这个,监听器必须知道CityWeatherPlugin中将监听器注册为监听气候信息监听器的方法。CityWeatherPlugin将负责记录并通知所有注册的监听器,它使用PropertyChangeEvent对象来给这些监听器提供信息。

class CityPopulationPlugin {
    ArrayList myListeners;
    // A public method that allows listener registration
    public void addPropertyChangeListener(IPropertyChangeListener listener) {
        if(!myListeners.contains(listener))
            myListeners.add(listener);
    }
    // A public method that allows listener registration
    public void removePropertyChangeListener(IPropertyChangeListener listener) {
        myListeners.remove(listener);
    }
    public CityPopulationPlugin (){
    // method to start the thread that invokes the population web service once every hour
    // and then notifies the listeners via the propertyChange() callback method.
        initWebServiceInvokerThread( myListeners );
    }

    void initWebServiceInvokerThread(ArrayList listeners) {
        // Code to Invoke Web Service Periodically, and retrieve information
        // Post Invocation, inform listeners
        for (Iterator iter = listeners.iterator(); iter.hasNext();) {
            IPropertyChangeListener element = (IProperty ChangeListener) iter.next();
            element.propertyChange(new PropertyChangeEvent(this, "CitiesWeatherXML" , null , CityWeatherXMLObj));            
        }
    }
}

Propertychange监听器必须实现org.eclipse.jface.util.IPropertyChangeListener接口来使propertychangeprovider可以使用回调函数。这个接口有一个方法:publicvoidpropertyChange(PropertyChangeEventevent).

class MyView implements IPropertyChangeListener {
    public void createPartControl() {
        //register with a Known Plugin that sources Population Data 
        CityPopulationPlugin.getInstance().addPropertyChangeListener(this);
    }
    public void propertyChange(PropertyChangeEvent event) {
        //This view is interested in the Population Counts of the Cities.
        //The population data is being sourced by another plugin in the background.
        if( event.getProperty().equals("CitiesWeatherXML")) {
            Object val = event.getNewValue();
            // do something with val
        }
    }
}

这种方法使应用程序可以在任何时刻通知监听器并通过自定义的Event传给他们信息。这些信息并不需要和UIselection有什么关系,可以是经过一些处理后的信息。例如它可以包含后台任务的描述或某个模型中包含的信息。例如,CitySelectorView可以不仅提供选择的城市信息,而且可以异步地将当前选择的城市气候信息推送到其他注册的View

总结

本文讨论了几种使View相互关联的方法。如果UIselection不能满足您的需求,那么可以考虑使用IAdaptable接口。属性变化监听器模式则更为灵活,尤其适用于包含非UI场景。


原文地址:http://www.ibm.com/developerworks/opensource/library/os-ecllink/

免责声明:文章转载自《Eclipse RCP中Viewer交互的三种方式/Make your Eclipse applications richer with view linking》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端测试Mock API工具——EoLinker API管理平台后台返回的json数据传到前端页面并在页面的表格中填充下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

浅析Android动画(二),属性动画高级实例探究

转载请注明出处!http://www.cnblogs.com/wondertwo/p/5312482.html ObjectAnimator实现属性动画 为了写好Android动画这几篇博客,在动笔之前我是下过很大决心的,我对自己的要求是尽量把一个小知识点写清楚写明白,说白了就是相对于大而全的长篇大论,我更倾向于去写小而美的博客!为了保证在高产的同时能坚...

深入理解Apollo核心机制之配置读取——ConfigService定时扫描

概述 之前我们了解了,客户端会每秒(默认)长轮询Config Service,等待通知,然后去主动拉取配置文件。本文主要跟进Config Service主动轮询ReleaseMessage表,并通知对应监听器的源码,最终终止客户端长轮询的源码。附上之前的链接《深入理解Apollo核心机制之配置读取——前言》 监听器介绍 Config Service中有一些...

Android控件系列之RadioButton&RadioGroup

学习目的: 1、掌握在Android中如何建立RadioGroup和RadioButton 2、掌握RadioGroup的常用属性 3、理解RadioButton和CheckBox的区别 4、掌握RadioGroup选中状态变换的事件(监听器) RadioButton和CheckBox的区别:1、单个RadioButton在选中后,通过点击无法变为未选中...

稳定UI运行结果-自动化测试失败重试和截图

运行自动化测试的时候,有时会因为网络不稳定,测试环境或者第三方环境正在重启而造成用例运行结果不稳定,时而能跑过时而跑不过。这些难以重现的环境因素造成的用例失败会让测试人员很困扰,排查即耗费时间也没有太多改善的空间。针对这种情况,我们可以基于TestNG的重试器和监听器实现失败结果的重试和监听处理,一旦监听到失败的测试用例,启动自己定制的重试方法和处理方法来...

java 监听器

java中的事件机制的参与者有3种角色: 1.event object:就是事件产生时具体的“事件”,用于listener的相应的方法之中,作为参数,一般存在与listerner的方法之中 2.event source:具体的接受事件的实体,比如说,你点击一个button,那么button就是event  source,这样你必须使button对某些事件进...

12、JavaEE--Listener监听器

监听器Listener 监听器基础 监听器介绍 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口 的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。 Servlet...