eclipse rcp详解Hello World以及eclipse rcp和osgi的简单展示(图文)
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的官方文档在这里:
如果想按照equinox的官方文档启动osgi框架的命令行,还得从eclipse的安装目录找到如下几个文件:
然后还需要这样一个config.ini文件:
代码如下:
才能够按照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能为我们提供哪些服务。