Eclipse RCP入门

Eclipse RCP入门

zhlmmc 2006-4-23

最近做了一个基于RCP的项目,感受颇深,觉得RCP有希望扭转Java桌面应用的颓势。在项目中积累了一点经验与心得,拿出来与大家分享,希望能给RCP初学者一点帮助。我研究Eclipse插件开发已经有一段时间了,但是我并没有很系统的学习过Eclipse的插件开发,往往只是做项目需要临时学的一点,所以讲的东西难免粗陋,请见谅。

一、Eclipse简介

Eclipse最初是由IBM捐献给开源社区的,目前已经发展成为人气最旺的Java IDEEclipse插件化的功能模块吸引了无数开发者开发基于Eclipse的功能插件。事实上,Eclipse已经超越了一般Java IDE的概念。Eclipse是一个平台,一个开放的平台,你可以为Eclipse添加任何你想要的功能,比如播放音乐,观看电影,聊天……这些不是天方夜谭,而是已经实现的事实。虽然Eclipse可以添加很多附加功能,可以编辑C/C++,可以编辑Word文件,可以开发UML等等,但是Eclipse最基本,也是最强大的功能还是Java IDE

二、RCP简介

RCP的全称是Rich Client Platform,可以把它看成是Eclipse的骨架,其他的插件是器官与血肉。我们可以把这个骨架拿过来填入自己的器官和血肉,这样就创造了我们自己的Eclipse

使用RCP来开发Java桌面应用可以把开发的焦点转移到系统的逻辑功能上,而不是界面上。我们自己的程序可以继承Eclipse的风格与功能,而不用自己去编写诸如菜单,工具条,子窗口等等的界面元素。甚至我们可以把Eclipse本身的功能插件,比如Console拿来放在自己的程序里,这样就避免了很多重复开发。

三、知识准备

我写这篇文章并不是面向Java的初学者,而是面向有一定Eclipse使用基础的开发者。所以我假设你已经具备一下基本知识:

1Java基础

2、 用过Eclipse进行开发

3SWT/JFace开发基础(可选)

如果你还不具备上述条件,那么看我的文章你会看的很郁闷,建议你先去学习这些基本知识。

四、Eclipse组件

在开发Eclipse插件(RCP可以看成是Eclipse的插件,只不过是脱离Eclipse运行的)之前,得先对Eclipse的结构有个了解。这里我简单介绍一下Eclipse的基本组件,这些名词可能比较陌生,但这都是开发Eclipse插件必须了解的。

如上图所示,我逐一介绍一个各个组件:

1Menu bar:这个东西你一定不陌生,每个软件都有的。不过Eclipse的菜单栏是动态的,也就是说,根据所编辑的内容不同,显示的菜单也可以不一样。

2Tool bar:这个东西也是每个软件都有的,和菜单栏一样,工具栏也是可以根据所编辑的内容不同而不同。

3Editor:编辑器,Eclipse的主要编辑工作是在Editor里面完成的。

4View:视图,视图是为了方便用户编辑提供一些辅助功能或编辑一些属性。比如最常见的Outline视图往往用来提供当前编辑的文档的结构。

5Page:页,一个页表示了当前用户的工作状态,包括ViewEditor

6Workbench Window涵盖所有上述组件的组件叫做工作台窗口(这个名词的翻译我没见到过,我这里纯粹是直译,感觉有些词不达意)。Eclipse是允许创建多个工作台的。通过Window->New window菜单可以创建当前工作台的副本。

除了这些组件以外我还要介绍另外两个概念,一个是Work Space,在Eclipse启动的时候都要求指定一个Work Space,而且Work Space是不能被共用的。也就是说在同一时间,同一个Work Space只可以被一个Eclipse使用。但是一个Work Space是可以被多个Workbench Window共享的。很容易联想到,Workbench Window上面还有一层Workbench。事实上Workbench才是EclipseUI的最高管理者。另外一个概念是Perspective,中文翻译是透视图(或者观察点)。所谓Perspective是指当前Page的布局。最常见的是Java透视图和Debug透视图,可以看到这两个透视图的Page排布完全不一样。通过切换透视图可以很方便的切换开发环境以完成不同功能的开发。这里可以看出ViewEditor的区别,Editor是在不同的透视图中共享的,而View不是。

五、开发前的准备

Eclipse是自带插件开发环境PDEPlug-in Develop Environment)的,所以要开发Eclipse插件只需要下载一个标准的Eclipse即可。我现在用的Eclipse版本是 3.3.0 ,是最新的稳定版,建议下载这个版本进行开发(我用的是英文版,所以下文提到的Eclipse相关的选项都是英文描述)。

虽然Eclipse生来就是开放的插件平台,但是Eclipse插件,特别是RCP是从3.0开始才走红的。Eclipse 3.0是一个具有里程碑意义的版本,它对Eclipse以前的结构做了一定的改进,并且升级了PDE,极大的简化了插件开发的配置,基本上实现了插件开发全图形的化操作,使得插件开发人员可以专注于插件功能的开发,而不用去管琐碎的配置文件。

六、第一个RCP程序

Eclipse提供了一些RCP程序的模板,通过PDE的插件创建向导能直接生成一个可用的RCP程序。

首先要新建一个Plug-in Project

然后输入Project名字,其他都用默认选项就行,点击next

Rich Client Application部分选择Yes,点击Next

模板选择Hello RCP,点击Next

点击Finish将提示转换到Plug-in development perspective,选择Yes

我们先看一下刚才新建的RCP的运行结果,右键点击Demoproject,选择Run As,选择Eclipse Application,就可以看到一个最简单的RCP程序窗口。

接下来我先分析一下这个应用程序的结构。在Demo包下面有六个类和三个配置文件,下面我解释一下这些元素:

六个类

三个配置文件

1Application:这个类是程序的入口,虽然没有Main函数,但是这个类实现了IPlatformRunnable接口,当JVM完毕,初始化RCP框架以后会调用这个类的run函数来完成UI设置和开始执行我们指定的程序功能。在绝大多数RCP程序中,这个类不用更改

2ApplicationActionBarAdvisor:简单的说这个类是用来配置程序的菜单栏和工具栏的,具体的应用在后面会讲到。

3ApplicationWorkbenchAdvisor:这个类是RCP程序的WorkbenchRCPEclipse的简化,但是所有的组件都是和Eclipse一样的。一个RCP程序也只能有一个Workbench

4ApplicationWorkbenchWindowAdvisor:这个类是RCPWorkbenchWindow,隶属于当前的Workbench。可以有多个WorkbenchWindow

5DemoPlugin:这个类代表了我们的插件,因为RCP程序也是一个插件,Eclipse中所有的插件都必须继承AbstractUIPlugin。这个类为我们提供了很多和插件相关的信息,比如插件的资源,配置等等

6Perspective:是我们新建的RCP的默认透视图。可以在这个类中指定ViewEditor的排布。

7plugin.xml:这个文件是我们插件的配置文件,包括我们的插件用了哪些其他的插件,具体是怎么配置这些插件的等等。

8build.properties:这个文件是用来配置我们插件的编译信息的,用来指定如何编译我们的插件。

9MANIFEST.MF:这个文件用来指定我们插件的元数据,比如插件的版本信息。一般来说,这个文件不用手动的去更改。

七、添加菜单和工具栏

这一节我演示以下如何为程序创建菜单和工具栏。在创建菜单和工具栏之前我想先介绍一个概念Action。开发Eclipse插件会经常看到这个东西,它和事件处理有点相似,如果你了解JFace的话,这里的Action你应该很熟悉,两者是一样的,我们自己定义的Action必须继承org.eclipse.jface.action.Action。程序可以定义当用户执行某项操作时触发某个Action。比如用户点击工具栏的一个按钮,或者选中了某个菜单项。

下面我们创建一个类HelloAction

package firstrcp;

 

import org.eclipse.jface.action.Action;

import org.eclipse.jface.resource.ImageDescriptor;

import org.eclipse.swt.SWT;

import org.eclipse.swt.widgets.MessageBox;

import org.eclipse.ui.IWorkbenchWindow;

import org.eclipse.ui.internal.IWorkbenchGraphicConstants;

import org.eclipse.ui.internal.WorkbenchImages;

 

public class HelloAction extends Action {

    private IWorkbenchWindow window;

 

    public HelloAction(IWorkbenchWindow window) {

       this.window = window;

       this.setText("Hello");

ImageDescriptor imgDes = WorkbenchImages.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV);

       this.setImageDescriptor(imgDes);

      }

}

由于Action是一个UI元素,所以往往创建一个带IWorkbenchWindow参数的构造函数,以便在Action内部调用。setText()是设置Action对外显示的名字。setImageDescriptor()是设置Action的图标,这里我为了简化,用的是Eclipse Workbench自带的图标。

下面增加一个run方法,功能是弹出一个对话框显示Hello World!

public void run() {

       MessageBox mb = new MessageBox(window.getShell(), SWT.OK);

       mb.setMessage("Hello world!");

       mb.setText("Demo");

       mb.open();

}

这里你可以看到构造函数传入window的好处了吧。

上述代码都很简单,我不多解释,接下来我们把创建的Action关联到菜单栏和工具栏上。我们可以把同一个Action同时关联到多个菜单项和工具栏按钮,这和事件处理中的事件处理函数可以被多个事件共享一样。

上文我已经提到过,ApplicationActionBarAdvisor是用来配置工具栏和菜单栏的,那么我们现在来看以下具体如何操作。修改ApplicationActionBarAdvisor如下:

package firstrcp;

 

import org.eclipse.jface.action.ICoolBarManager;

import org.eclipse.jface.action.IMenuManager;

import org.eclipse.jface.action.IToolBarManager;

import org.eclipse.jface.action.MenuManager;

import org.eclipse.jface.action.ToolBarContributionItem;

import org.eclipse.jface.action.ToolBarManager;

import org.eclipse.swt.SWT;

import org.eclipse.ui.IWorkbenchWindow;

import org.eclipse.ui.application.ActionBarAdvisor;

import org.eclipse.ui.application.IActionBarConfigurer;

 

public class ApplicationActionBarAdvisor extends ActionBarAdvisor {

    private HelloAction helloAction;

 

    public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {

       super(configurer);

    }

 

    //用来初始化action

    protected void makeActions(IWorkbenchWindow window) {

       super.makeActions(window);

       helloAction = new HelloAction(window);

    }

 

    /* 用来设置菜单栏.创建一个MenuManager,然后把helloAction加入到这个菜单下面,

     * 如果有多个action的话,可以加入同一个MenuManager

     * 这样demoMenu相当于一个下拉菜单,

     * 而加入的action就是菜单项。最后把demoMenu加入到菜单栏。

     */

    protected void fillMenuBar(IMenuManager menuBar) {

       super.fillMenuBar(menuBar);

       MenuManager demoMenu = new MenuManager("&Demo", "");

       demoMenu.add(helloAction);

       menuBar.add(demoMenu);

    }

 

    /*

     * 用来设置工具栏的,原理和菜单栏是一样的,coolBar也有分组的,

     * 每个toolbar就是一组。这里的toolbar相当于demoMenu

     */

    protected void fillCoolBar(ICoolBarManager coolBar) {

       IToolBarManager toolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT);

       coolBar.add(new ToolBarContributionItem(toolbar, "main"));

       toolbar.add(helloAction);

    }

}

代码看起来有点晕,我来一一解释。首先是makeActions()方法,这个方法是用来初始化action的,所有要用到的action可以都在这里初始化,但是这一步与界面无关。fillMenuBar()是用来设置菜单栏的。先创建一个MenuManager,然后把helloAction加入到这个菜单下面,如果有多个action的话,可以加入同一个MenuManager,这样demoMenu相当于一个下拉菜单,而加入的action就是菜单项。最后把demoMenu加入到菜单栏。当然,一个菜单栏可以加入多个下拉菜单。多级菜单也是可以做的,有兴趣的可以自行研究。fillCoolBar()是用来设置工具栏的,原理和菜单栏是一样的,coolBar也有分组的,每个toolbar就是一组。这里的toolbar相当于demoMenu

运行一下程序你会发现菜单栏出来了,但是工具栏没有出现。原因是Hello RCP默认是不显示工具栏的,我们得改一下设置。打开ApplicationWorkbenchWindowAdvisor类,更改preWindowOpen方法:

public void preWindowOpen() {

        IWorkbenchWindowConfigurer configurer = getWindowConfigurer();

        configurer.setInitialSize(new Point(400, 300));

        //configurer.setShowCoolBar(false);

        configurer.setShowStatusLine(false);

        configurer.setTitle("Hello RCP");

}

以上代码也很简单,从字面就能看出什么意思,我也不多解释,注意看注释掉的那行。preWindowOpen()这个函数在程序的窗口打开之前被调用,可以在这个函数里设置一些初始化的内容。类似的还有postWindowClose()等等,你可以查阅API来了解这些函数的用途。

现在我们的程序可以正确的运行了,看一下运行结果:

八、创建ViewEditor

我用Designer来编辑ViewEditor。我用的版本是WindowBuilder Pro 4.1.0 ,建议你也去下载一个,因为这个插件能够支持SWTJFaceRCPSwing的可视化编辑,极大的缩短了界面开发的时间。不过这个是商业软件,要破解了才能用,网上有很多破解的方法,google一下就行了。

下面开始创建第一个View

右键点击demo包,选择NewOther 然后选择Designer->RCP->ViewPart,点击Next

输入HelloView,点击Finish

你可以在SourceDesign之间切换。View相当于一个窗口,在View的界面上可以放任何组件。我拖了一个button上去,名字就叫buttonHelloView类中要添加一个属性ID,我稍后解释这个属性。

你可以用同样的方法创建一个EditorPart,名字就叫HelloEditor。在editor上面放一个text组件吧,这样看起来像个editor,然后把HelloEditorlayout改成FillLayout。当然也要为HelloEditor添加一个ID属性。这里需要改一下Editorinit方法,否则editor无法正常运行。

setSite是让editor能够使用workbench所提供的一些功能,EditorSite可以看成是一个代理,EditorPart通过EditorSite来访问workbenchEditorSiteeditor partworkbench之间的一层接口,详细情况你可以去google一下或者参考APIsetInput的意思就很明了,就是让editor知道显示什么东西。这样我们就创建好了基本的ViewEditor,下面来看怎么把它们加到我们的程序中去。

打开plugin.xml,选择Extensions标签页,在All Extensions部分点击Add按钮,选择org.eclipse.ui.views, org.eclipse.ui.editors, 两个extension,结果如下:

右键org.eclipse.ui.view,选择New->view

Extension Element Details部分设置View的属性。ID可以随意设置,但是不能重复,我这里设置为Demo.helloView(虽说是随意设置,但是程序是通过这个ID来获得View的,所以最好与HelloView中的ID属性一致,我在HelloView中加入这个ID属性也是为了方便程序获得HelloView),Name也可以随意设置,我这里设置为Hello View,这个属性会显示在View的顶端,就像Outline View顶部显示的名称是Outlineclass选择刚才创建的demo.HelloViewicon是显示在View顶部的图标,没有可以不设置。

类似的创建Hello Editor,设置Hello Editor的详细属性,设置id, name, class三个属性以外,还要设置icon属性(EditorIcon属性是必须的!),随便给个图片文件就行,其他的属性可以不填。这里属性比较多,有兴趣可以去看Eclipse的插件开发帮助,里面对每个属性都有解释。

到目前为止,我们的配置工作已经完成,但是要让我们的程序正确的显示ViewEditor,我们还要更改默认的Perspective。打开Perspective.java,修改createInitialLayout()方法(默认这个方法是空的)

public

这个方法实际上就是修改layout,在这个方法中安排每个view的位置和大小。addStandaloneView()是为当前的Perspective添加一个独立的View,所谓独立的View就是View所占的位置不能和其他View共享,你在Eclipse里应该看到过几个View叠在一起的情况。接下来一行设置是去除了关闭View的功能,就是这个View的顶部没有关闭按钮。我们来看一下运行结果

 

void createInitialLayout(IPageLayout layout)

{

layout.addStandaloneView(HelloView.ID, true,

IPageLayout.LEFT, .50f , layout.getEditorArea());

layout.getViewLayout(HelloView.ID).setCloseable(false);

}

也许你正在想怎么打开EditorIPageLayout并不能直接把一个Editor加入显示,但是它会预留一块空间给Editor。如果你仔细观察上面那段代码,你会发现,事实上整个空间都是Editor的,View是在瓜分Editor的空间。接下来我将介绍如何打开Editor

九、设置并打开Editor

相对View来说,Editor有点麻烦。因为要打开Editor的话必须给Editor内容,因为Editor是个编辑器,你得让它知道要编辑什么东西它才能打开。这里的内容就是Eclipse里面的EditorInput。没有现成合适的EditorInput用(一般情况下可以用FileEditorInput,把某个文件作为InputEditor打开,在Eclipse里面双击打开某个文件就是这个过程),我这里创建一个HelloEditorInput继承IEditorInput接口。用Eclipse向导创建类的时候,先选择Interface,然后记得选中Inherited abstract methods,这样会自动继承所有abstract的方法,不用再去手工创建了。

HelloEditorInput的代码比较长,我不全部贴出来了,我贴一部分。我贴的两个方法是必须要修改的,这个类的其他代码用Eclipse自动生成的就好(做实际开发的时候肯定是要改的,我这里只是演示一个过程,所以尽量简化了)。

public

这里的getName是返回当前input的名字,比如文件名,getToolTipText是返回当前input的提示,当鼠标移动到editor的顶部标签上时就会显示。这两个方法都不能返回null

好了现在一切准备工作已经就绪,就等打开Editor了。我们通过HelloView上面的那个按钮来打开HelloEditor,每按一次按钮打开一个Editor。首先更改按钮的Text属性为Open Editor,然后为按钮添加事件,事件代码如下:

关键代码就一行,就是那个openEditor方法,这个函数的两个参数,前面的代表资源,后面的代表工具,就是用后面的Editor去打开前面的内容。提醒一下,这里的Editor ID必须和plugin.xml文件里面的一样,否则会找不到合适的Editor。可以看到openEditorPage的方法,这也和我前面介绍的Eclipse的组件结构一致,ViewEditor是属于某个page的。其实在配置Perspective的时候也能看出这个问题,我们都是用IPageLayout

 

String getName()

{

return "Hello";

}

public String getToolTipText()

{

return "Demo";

}

 

openEditorButton.addSelectionListener(new SelectionAdapter()

{

public void widgetSelected(SelectionEvent e)

{

try

{

getViewSite().getWorkbenchWindow().getActivePage()

.openEditor(new HelloEditorInput(), HelloEditor.ID);

}

catch (Exception ex)

{

System.out.println(ex);

}

}

});

来布置界面。下面运行一下程序,看一下运行结果。

可能你会感觉不太协调,那么我们把窗口默认最大化(似乎能好看点),这就需要修改ApplicationWorkbenchWindowAdvisor类中的postWindowOpen函数:

如果你以前接触过SWT/JFace的话这段代码应该很熟悉吧,就算没接触过,也应该能大概明白什么意思,所以我不解释了。这句话一定要放在postWindowOpen里面,因为在preWindowOpen的时候还没有Window存在,所以没法设置。我们来看一下最终的运行结果:

下面我介绍一下如何导出/发布RCP程序,使程序能够独立运行。

 

public void postWindowOpen()

{

this.getWindowConfigurer().getWindow().getShell().setMaximized(true);

}

十、导出RCP程序

Eclipse 3.0开始,RCP程序的配置和导出就变得相当方便。RCP程序又称为Eclipse Product,我们先为Demo Project新建一个Product配置文件。右键Demo Project,选择New->Other->Product Configuration,然后选择Demo文件夹,File name输入demo.product,点击Finish

接下来我们要新建一个Product Id,点击New

然后点击Browse选择Demo,并输入Product IDhello,点击Finish

Overview标签页的Product Definition部分,输入Product NameHello Demo。在Testing部分点击一下Synchronize(最好点一下,有时候不点也没问题),这是为了让我们的Product配置和插件的配置保持一致。然后切换到Configuration标签页,点击Add,输入Demo,点击OK

然后点击Add Required Plug-ins,这一步是添加我们的Product所用到的其他插件,这样才可以脱离Eclipse运行。

然后进入Branding标签页,这一页是设置Product的图标,程序名字等等,可以不设置,系统会自动使用默认值,我这里输入一个Launcher NameHelloDemo

现在我们已经完成了导出的配置工作,现在来导出我们的RCP程序。进入Demo.productOverview标签页,在右下角Exporting部分点击Eclipse Product export wizard,输入Root DirectoryExport Destination,点击Finish

到这里为止,我的例子就结束了,你可以到你export的地方去找HelloDemo.exe(文件名根据设置不一样而不一样),然后双击打开就可以看到效果了。我的这个例子只是演示一个RCP程序开发的流程,中间有很多细节都省略了,真正做RCP开发的时候还要考虑很多问题。如果在开发中遇到什么困难我建议去http://www.eclipse.org寻找帮助,那里有很多文章,新闻组的人气也很旺,牛人特别多。

 

你可能感兴趣的:(java,eclipse,application,action,import,工具)