京山游侠

专注技术,拒绝扯淡
posts - 50, comments - 868, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
现状:
  五年前,我在博客中发了一系列用Eclipse RCP进行桌面开发的文章,最高访问量达到了5万多。那个时候,Eclipse RCP技术正刚刚起步,参考资料不是那么好找。五年后,当我再次关注Eclipse RCP时,它早已是如日中天,但国内的参考资料仍寥寥无几。所以我决定再次写一些关于Eclipse RCP的东西。
  GUI桌面编程这个话题本来就非常不好写。这么多年,这么大一个领域,真真正正能写成像《深入浅出MFC》这样的经典的书籍没有几本。纵观国内在该领域出版的书籍,要么就是大篇大篇罗列这个控件那个控件怎么用,控件有哪些属性可以设置,有哪些事件可以处理;要么就是大段大段贴代码,而对于GUI编程的一些本质、一些哲学性的东西没有深入的分析。在Eclipse RCP领域尤其如此,有那么几本打着Eclipse RCP和OSGi大旗的书籍,但是其参考价值却不比Eclipse自带的帮助文档大多少,大有圈钱的嫌疑。
  Eclipse RCP是个好东西。用Eclipse RCP写桌面程序,可以在一个很高的起点上构建自己的窗口应用,至于那种从头开始写窗口的日子是再也不复返了,甚至美工都不需要自己考虑了。(想想VC领域有多少界面库在折磨着程序员。)还有一个好处当然是跨平台了,虽然要背上一个Java虚拟机的负担。(现在的Eclipse RCP程序导出时可以自己包含JRE,又大大简化了程序部署的过程。)
  五年前我写的那几篇博文有很多缺点,缺点一是其中有些东西我自己都没有搞懂,所以没办法写得太深入;缺点二是跳跃性太大,总共才六篇,我却又是展示COM组件,又是展示OpenGL,虽说让大家在视觉上是狠狠体验的一把,但是一点也不系统。所以这次一定要改变这些缺点,争取做到以下目标:

目标:
  1.言简意赅,对于那些有助于理解Eclipse RCP平台的核心概念重点点出,并结合实例。对于那种在Google上一查一大把的废话坚决不写;
  2.争取系统性地介绍Eclipse RCP平台可用的特性及其背后的一些设计模式,不再浮光掠影地一飘而过,也不专写冷门偏门;
  3.不追求面面俱到,有些用不到的东西肯定没必要讲,也不怕别人说我水平差;
  4.当然是大量展示图片啦。

好了,下面开工,首先,当然是创建一个Hello World,初步展示一些Eclipse RCP的效果。Eclipse RCP编程的本质就是利用Eclipse的插件机制,在Eclipse的Runtime上进行扩展来构建我们自己的窗口程序,所以,创建项目的时候当然是创建一个Plug-in Project了。只是在下面那个“Would you like to create a rich client application ?”的地方选择yes即可。


一路Next下去,我就不多截图了。在选择应用程序模板的时候,选择最简单的Hello RCP即可。如果这时运行程序(用Run As -> Eclipse Application),可以得到一个简单的窗口。

为了显示Hello World,我们需要一个扩展一个View。创建一个View类,其基类为org.eclipse.ui.part.ViewPart,如下图:


在HelloWorldView的代码中,我们只需要一个SWT中的Label控件用来显示HelloWorld,如下图:


下一步,就要把这个HelloWorldView插入到窗口中,这个可以通过配置Plugin的Extension来实现。打开plugin.xml的编辑器,增加一个org.eclipse.ui.views的扩展,如下图:


在Eclipse中,扩展的View并不是马上显示到前台,而是要通过菜单Window->Show View来显示,或者将View关联到某个透视图,切换透视图的时候显示这个View。我们的RCP程序的目标是单独运行,而不是当插件安装到Eclipse中,追求的是一运行程序就显示这个View,所以还要扩展org.eclipse.ui.perspectiveExtensions。如下图:


运行程序,看看效果。通过Run As -> Eclipse Application运行,如下图:


到现在,我们的工作完成一半,因为该程序还只能在Eclipse中运行,要想脱离Eclipse单独运行,必须将其作为单独的产品导出。要导出产品,先要新建一个product configuration,然后进行配置。为简单起见,我们只需要配置三个地方。
第一个地方:Application,这个关系到程序的启动点


第二个地方,launcher,这个可以生成一个像eclipse那样的本地启动程序


第三个地方,依赖项,可以先把自己添加到依赖项中,然后再点Add Required Plug-ins按钮添加所有需要的依赖项




我自己第一次接触Eclipse RCP时,就经常因为不把自己添加到依赖项中而造成程序启动失败。

下一步,导出程序,如下图:


在以上对话框中,我把能省的空都省了。最后得到的目标程序文件夹内容及运行程序的效果如下图:


以上过程非常简单,所以先秀图片。下面,来看看Eclipse RCP和OSGi的一些概念。
  1.Bundle和Bundle的生命周期:Bundle是OSGi的一个概念,我们可以把它理解为模块、插件,如果仅仅只是学习Eclipse RCP编程的话,就不需要对OSGi进行深入学习,虽然它很流行。但是一些基本的概念还是要知道的。Eclipse完全构建在OSGi之上,它包含有一个OSGi规范的完整实现Equinox。所以Eclipse的一个Plug-in,基本上就等于OSGi的一个Bundle。我们不需要特意去编辑Bundle的定义文件META-INFO/MANIFEST.MF,在编辑plugin.xml的时候,Bundle的定义文件会自动更新。一个Bundle被安装到OSGi系统中后,并不会马上启动,只有当这个Bundle提供的功能被调用的时候,该Bundle才会被启动,当该Bundle不被用到的时候,它就可以被停止。在一个Bundle的生命周期中,我们可以定义自己的Activator来处理启动、停止等各个阶段的任务,这就是我们前面的例子中为什么要定义一个Activator的原因。通过Activator,我们可以查看OSGi系统中安装的所有Bundle,因为OSGi系统调用Activator中的方法时,会传递一个BundleContext参数,使用该context,我们可以完全访问整个OSGi系统的功能。
  2.Plug-in之间或Bundle之间的依赖关系:由于Plug-in和Bundle基本上是同义词,所以在后文中我将不提Bundle。Eclipse的Plug-in机制早已深入人心,一个Plug-in经常会依赖于其它的Plug-in,这已经成为常识,不需要我赘述。Plug-in的定义中最重要的就是它的ID和Version,靠这两个字段就可以唯一标识一个Plug-in,所以在前面的例子中,凡是出现ID的地方,我都很认真填写,并且使用com.xkland.....这样的形式来定义ID,避免出现冲突。对于Name、Vendor这样的字段,明显是给人阅读的,所以就随便填一填。
  3.还有比Plug-in更小的单位,那就是Package:虽然说Eclipse中的Plug-in是一个很小的单位了,但是还有更小的,那就是Package。如果有人不想依赖整个Plug-in的话,也可以单独只Import几个Package。当然,对于我们自己写的Plug-in,也可以export一些Package供别人使用。在plugin.xml的编辑器中,有一个专门的页面是用来设置和Package相关的内容的。在前面的例子中没有演示这一点,因为我觉得我写的程序还没有必要分这么细。
  4.Extension和Extension Point:这个好像也早就是Eclipse领域常识性的概念了吧。在Plug-in中可以定义一些Extension Point,在别的Plug-in中可以扩展这些Extension Point。比如在前面的例子中,我们自己的Plug-in扩展了org.eclipse.core.runtime插件(叫Bundle可能更合适)和org.eclipse.ui插件定义的几个扩展点,这些定义实在plugin.xml编辑器的Extensions页面定义的。当然,我们的程序没有定义自己的Extension Point,因为不需要让别人去扩展什么。
  5.Product不是个什么重要的概念,从前面的例子可以看出,我们定不定义Product的ID都没什么影响。不过要导出Product的时候,application一定要指定,依赖项也要搞清楚,因为这关系到我们的程序能不能成功运行。

  好了,概念性的东西就将这么多。OSGi不需要深究,因为我们会直接和Eclipse的Runtime打交道,以后会有专门的章节讲Eclipse的Runtime提供有哪些服务。下面的例子演示即使不使用Native launcher,也可以通过OSGi框架启动我们的Hello World。
  在导出Product的时候,选择如下图中的单选框和填写好根目录:

  就可以得到一个Repository,该Repository是供p2安装程序使用的,里面没有Native launcher。如下图:

  在这个目录里面建立一个configuration文件夹,里面放一个config.ini,记住,在Linux系统下,configuration文件夹一定要是rwx权限的哦。config.ini文件内容如下:

  该文件定义了OSGi启动时安装哪些Bundle,并且这些Bundle默认的启动级别是多少。启动级别的数字越小的越优先启动。configuration/config.ini是OSGi启动时默认的配置文件路径,当然也可以使用-configuration选项更改为别的路径。然后,如下命令启动HelloWorld:

  在指定启动OSGi的jar文件时,我偷了点懒,为了少敲几下键盘,使用了一个通配符,大家还是可以很轻松地看出来是哪个文件哦?Equinox的官方文档在这里:http://eclipse.org/equinox/documents/quickstart-framework.php
  如果想按照Equinox的官方文档启动OSGi框架的命令行,还得从Eclipse的安装目录找到如下几个文件:

  然后还需要这样一个config.ini文件:
osgi.bundles=./org.apache.felix.gogo.runtime_0.10.0.jar@start,
     ./org.apache.felix.gogo.command_0
.12.0.jar@start,
     ./org.apache.felix.gogo.shell_0
.10.0.jar@start,
     ./org.eclipse.equinox.console_1
.0.0.dist.jar@start,
 osgi.console.enable.builtin
=false 
 osgi.console
=<port> 

  才能够按照Equinox的文档那样用java -jar org.eclipse.osgi_3.8.1.dist.jar -console启动OSGi框架的命令行。

  从Hello World这个例子可以看出,我们的Eclipse RCP程序构建在org.eclipse.core.runtime和org.eclipse.ui这两个Bundle上。下一篇,我将为大家讲述这两个Bundle能为我们提供哪些服务。

下一篇
Eclipse RCP详解(02):Eclipse的Runtime和UI初探

评论

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-01-09 10:02 by 鹏达锁业
过来学习一下。欢迎回访

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-02-19 10:11 by Phnix
Eclipse RCP e4与以前的比,有了很大的改动,比如css样式支持之类,看LZ用的是3.x版本,LZ能否讲些e4版本方面的知识,网上相关的信息好少。

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-02-19 22:37 by 海边沫沫
@Phnix
Eclipse Wiki的RCP页面中,有一个e4 RCP的tutorial很不错。
另外,直到目前的eclipse 4.3,e4 RCP的API都不是完整的,估计要期待ecliple 4.4。

我的这一系列博文是有计划的,准备讲完eclipse 3.x RCP中的JFace和结构化数据,Core expression,Editor后,然后介绍e4 RCP。而且我在等Ubuntu 14.04的发布,因为我现在用的Eclipse 3.8.1是Ubuntu 13.10自带的,它的特点就是在Ubuntu中使用非常漂亮,而我自己从eclipse官网下载的达不到这种效果。我希望14.04中自带的是eclipse 4.x版。然后很自然过渡到e4 RCP。

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-02-20 09:15 by Phnix
@海边沫沫
嗯。而且目前e4的资料还不够丰富,碰到问题比较让人着急。网上一搜,好多都是针对3.x版本的答案。

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示[未登录]  回复  更多评论   

2014-02-26 14:56 by haha
请问eclipse是什么版本啊,怎么我的不一样呢

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-02-26 20:15 by 海边沫沫
@haha
我用的是Ubuntu 13.10中自带的Eclipse 3.8.1
我估计Ubuntu团队对它的界面做了一点点改变,以便更符合Ubuntu的主题
所以和别的系统中的Eclipse有点不一样

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-03-14 13:23 by gaesar1
老师,你好。我是个初学者。我的扩展点怎么建立不起来呢?运行后没有显示,而且我的扩展点也没向你的那样有那么多标签选项,和下划线链接。是不是我哪里设置不对啊?

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-03-14 20:35 by 海边沫沫
@gaesar1
需要一点耐心,仔细做好每一个步骤。把Eclipse自带的几个RCP模板都生成一下,看一下每一个模板生成的程序有什么不同,是一个很好的起步手段。

另外,可以看看我五年前的博文(向后翻几页就到,我的Blog文章不多)。那个时候写的Hello World可能更详细。

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-03-17 13:30 by gaesar1
老师,我生成了几个模板还是没有头绪。成了带有一个视图的helloRCP,为什我把原扩展的class和id均指向一个新的视图时(perspectiveExtension也改了),运行还是提示原来的视图无法创建呢?

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-09-27 23:28 by enjay
最近看了你写的Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示文章,知道你研究RCP时间比较长,我想请教一下,开发RCP时,两个plug-in依赖时,为什么在eclipse中运行ok,而当发布出来时却报如下错误:
Could not create the view: Plug-in com.enjay.rcp.railway was unable to load class com.enjay.rcp.railway.home.HomeView.
我写的HomeView是继承另一个plug-in的视图。
请指教,期待你的回复,谢谢

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-10-01 20:55 by 海边沫沫
@enjay
你的问题就是很简单的在发布的时候没有把相应的plugin发布出来。
所以在eclipse中运行OK,单独运行时就找不到HomeView了。

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-12-26 10:32 by fenghuozhuan
怎么能全部档下来

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2014-12-26 10:32 by fenghuozhuan
对了,写的很好,很喜欢

# re: Eclipse RCP详解(01):Hello World以及Eclipse RCP和OSGi的简单展示  回复  更多评论   

2015-08-15 12:53 by shaoalan
很不错,楼主用心了

只有注册用户登录后才能发表评论。


网站导航: