eclipse plug-in 的开发-- Rich Client 教程

zhuan zi: http://www.benisoft.com/cn/java/index.htm

Rich Client 教程 第一部分

Rich Client Platform (RCP)是一种全新的建立Java应用的方式,它完全不逊色于任何为专门平台开发的应用。本教程帮助你快速建立一个RCP应用,并被更新以适用于Eclipse 3.1。

作者 Ed Burnette, SAS
2005年7月更新适用Eclipse 3.1

译者 Cliff Liang
2005年8月


简介

尝试一下:将Eclipse给你那些以前从来没有接触过Eclipse的朋友或同事看,并让他们猜猜看Eclipse是用什么语言写的。他们有可能猜是VB,C++,或C#,因为这些语言被广泛用于开发高质量的客户端应用。当你告诉他们Eclipse是由Java语言开发的时候,看看他们会有什么样的表情, 尤其是他们自己就是Java程序员的话 。

由于Eclipse独特的开放源码许可证,你可以使用Eclipse技术来创建你自己的商业质量的程序。在Eclipse 3.0以前,这也是可能的,但有点困难,尤其是你需要高度定制菜单,布局,和其他用户界面元素的时候。这是因为Eclipse完全是按照IDE的标准设计的。Eclipse 3.0引出了Rich Client Platform(RCP),它基本上重构了Eclipse用户界面的基础部分,使得它可以用于非IDE应用。Eclipse 3.1为RCP提供了新的功能,最重要的是,提供新的支持使工具创建更容易。

如果你想停一下,看看第一部分的代码,你可以在这里下载它们。接下来,我们来看看如何创建一个RCP应用。

开始

RCP应用给予Eclipse plug-in架构,(如果你不熟悉,可以查看参考部分的内容)。因此,你需要为你的主程序建立一个plug-in。Eclipse的plug-in开发环境Plug-in Development Environment(PDE)为开发过程提供了大量的向导对话框和编辑器。选择File > New > Project > Plug-in Development > Plug-in Project,就会显示plug-in项目的向导对话框。在后面的页面中,输入项目名,比如org.eclipse.ui.tutorials.rcp.part1,选择Create a Java project,选择你所针对的Eclipse版本,并选择Create an OSGI bundle manifest for the plug-in。然后点击Next

Note: 如果你使用Eclipse 3.1,你最好选择Create an OSGI bundle manifest for the plug-in。和以前的版本相比,现在这个选项缺省是被选中的。

在向导的下一个页面中,你可以修改plug-in的ID和其他参数。一个重要的问题是,“Would you like to create a rich client application?”。选择Yes。创建一个plug-in所代表的类是可选的,但是对于这个例子,其他选项都可以使用缺省值。选择Next继续。

在Eclipse 3.1中,提供了许多创建RCP应用的模版。这里我们使用最简单的模版。选择Create a plug-in using one of the templates,然后选择Hello RCP模版,这相当于是RCP的“Hello,World”。点击Finish生成项目。Eclipse会打开plug-in的Plug-in Manifest Editor。这个编辑框可以编辑配置来控制你的RCP应用。

Note: 如果你看到一个对话框询问你是否切换到Plug-in Development透视图,你可以点击Remember my decision,并选择Yes

运行一下看看

尝试RCP应用在以往是有点乏味的。你必须创建一个运行配置,提供正确的应用名,并且还有找到所有需要的plug-in。幸运的是,现在PDE可以处理所有的这些。你所要做的仅仅是在Plug-in Manifest编辑器的Overview页中点击Launch an Eclipse Application。你就能看到启动了一个基本的Workbench。(图 1)

图 1. 最简单的RCP应用

创建一个Feature

在Eclipse里,feature是plug-in的集合。Feature是可选的,但是Eclipse推荐你使用feature,这是因为如果你需要通过Eclipse的自动更新管理器来安装、更新你的应用,或者使用JNLP导出应用,feature就能帮助你做到这些。要创建feature,选择File > New > Project > Plug-in Development > Feature Project。一般feature的名字是你的plug-in项目名加上“-feature”,所以我们这里创建的feature就叫org.eclipse.ui.tutorials.rcp.part1-feature。点击Next来到Feature Properties页面,再点击Next,来到Referenced Plug-ins and Fragments 页面。选择org.eclipse.ui.tutorials.rcp.part1,点击Finish,这样feature项目就创建好了。

建立product

用Eclipse的话来说,product就是任何构成你的应用的东西,包括所有它所依赖的plug-in,运行应用的命令,以及使你的应用区别于其他应用的商标(图标等)。虽然你运行一个RCP应用并不需要定义product,但是这样做可以使得你应用脱离Eclipse运行变得更容易。这是Eclipse 3.1为RCP开发带来的重要改进。

许多复杂的RCP模版随着product一起提供,例如,“RCP Application with an Intro”和“RCP Mail”。更多的模版会在今后的版本中提供。Hello RCP这个模版没有定义成product,所以我们就为它建立一个product。

为了建立product,你首先为项目添加一个product定义文件。右键点击plug-in项目,选择New > Product Configuration。然后输入配置文件的文件名,比如part1.product。选择Use a launch configuration,和下拉列表中的Eclipse Application。(注意如果你在当前的workspace中有其他的plug-in项目,你有可能会看到一个不同的运行配置名。选取和你刚才运行的RCP plug-in相关的运行配置)然后点击Finish。这时会出现product配置编辑器。通过这个编辑器,你可以控制你的product中所需要的plug-in和商标。

Overview页面中,输入Product Name,比如RCP Tutorial 1。选择This project configuration is based on features。然后选择New...按钮创建一个新的product。输入product的Defining Plug-inorg.eclipse.ui.tutorials.rcp.part1。输入Product ID,比如product,Product Application选择org.eclipse.ui.tutorials.rcp.part1.application。点击Finish

Note: 在Eclipse 3.1中,如果你在输入Product Name前创建product,你会在Problems视图中看到错误。这个错误在你Synchronize后会消失。这是一个已知的bug,会在今后的版本中修复。

回到Product Configuration编辑器的Overview页面。点击product configuration链接或者选择Configuration页面,添加你的feature(org.eclipse.ui.tutorials.rcp.part1_feature)和RCP的feature(org.eclipse.rcp)。然后回到Overview页面,按 Ctrl+S或者File > Save保存。

这时,你应该测试你的product,确保它能正确运行。在Overview页面的Testing部分,点击Synchronize,然后点击Launch the product。如果运行正常,应用应该和刚才看到的结果一样。

在Eclipse外运行

所有这些都是为了能在用户对Java和Eclipse一无所知的情况下运行独立的应用。对于一个真实的应用,你可能提供由InstallShield这样的安装程序生成的可执行程序。这超出了本教程的范围,所以我们会用简单的方式来演示。

我们需要建立一个简单的Eclipse安装目录,这是因为Eclipse plug-in装载器希望所有的plug-in都在恰当的位置。这个目录必须包含可执行的Eclipse启动程序,配置文件和所有product需要的feature和plug-in。我们为此定义了足够的PDE信息。

Product Configuration编辑器(不是Plug-in Manifest编辑器)中,点击Eclipse product export wizard。修改根目录为RcpTutorial1。然后选择Export DestinationDirectory,并输入目录名,比如C:/Deploy。如果你正在建立一个开放源码的项目,你可以选择Include source code。最后点击Finish

现在,应用就可以在脱离Eclipse的情况下执行。当你完成后,你应该得到下面的目录结构:

    RcpTutorial1
    |    .eclipseproduct
    |    eclipse.exe
    |    startup.jar
    +--- configuration
    |    |    config.ini
    +--- plugins
    |    |    org.eclipse.core.commands_3.1.0.jar
    |    |    org.eclipse.core.expressions_3.1.0.jar
    |    |    org.eclipse.core.runtime_3.1.0.jar
    |    |    org.eclipse.help_3.1.0.jar
    |    |    org.eclipse.jface_3.1.0.jar
    |    |    org.eclipse.osgi_3.1.0.jar
    |    |    org.eclipse.rcp_3.1.0.jar
    |    |    org.eclipse.swt.win32.win32.x86_3.1.0.jar
    |    |    org.eclipse.swt_3.1.0.jar
    |    |    org.eclipse.ui.tutorials.rcp.part1_1.0.0.jar
    |    |    org.eclipse.ui.workbench_3.1.0.jar
    |    |    org.eclipse.ui_3.1.0.jar
    |    |    org.eclipse.update.configurator_3.1.0.jar
    +--- features
         +--- org.eclipse.ui.tutorials.rcp.part1_feature_1.0.0
         +--- org.eclipse.rcp_3.1.0

Note: 在Eclipse 3.1,推荐的plug-in格式是一个jar文件。这在部署应用的时候可以节省存储空间。

Tip: 本教程的以前版本使用批处理文件或shell脚本来启动你的RCP程序。 现在看来,这是一个不好的办法,因为你不能完全为你的应用定制商标信息。例如,你不能添加启动画面。所以务必使用Eclipse可执行的启动程序。

试试看吧!在Eclipse外执行可执行启动程序,看看它能不能工作。启动程序的名字(缺省是“Eclipse”)可以在product配置的时候在商标选择中设置。

问题解决

在我写本教程的早些版本中,我收到邮件说他们由于这样或那样的原因不能运行例子。许多的意见已经在新的PDE设计中有所改善,所以没必要将它们列在这里。因此我现在将这一节暂时留着空白。如果你在运行应用时有任何问题,请告诉我,我将加以解决一般其他人能看到。

兼容性和移植

如果你正在将一个Eclipse 2.1版本的plug-in移植为Eclipse 3.1版本,你需要参考在线文档中所提到的一些问题。如果你是移植Eclipse 3.0版本的plug-in,那问题会少很多。更多的信息可参阅参考部分。

Tip: 建议:当心不要使plug-in.xml和MANIFEST.MF的内容有所重复。一般不会这样,除非你将一个不使用MANIFEST.MF的老plug-in转换成使用MANIFEST.MF的,而且是手工编辑这些文件二没有借助于PDE。

结尾

在本教程的第一部分,我们看到建立一个Rich Client的简单应用需要哪些必要的步骤。下一部分将深入介绍那些由向导建立的类,比如WorkbenchAdvisor。所有的例子代码可以在这里找到。

 

Rich Client 教程 第二部分

Rich Client Platform (RCP) 使你可以创建出能和任何平台的原生应用匹敌的Java应用 。教程的第一部分向你介绍了用来创建最简单的RCP程序的所用到的平台和步骤。在第二部分中,我们将更详细地了解我们做了哪些,并且介绍一些配置类使得你可以控制RCP应用的外观和功能。

(译,本教材适用于Eclipse 3.0,并在不久为Eclipse 3.1作更新)

作者 Ed Burnette,SAS
译者 Cliff Liang,BeniSoft

2004年8月9日


简介

在Eclipse 2.1中,Eclipse IDE的许多功能是由固定的代码实现的。这包括File菜单的名字和位置,Wrokbench窗口的标题,以及状态栏的存在与否。这对于IDE来说并没有什么不好,但是当有人使用Eclipse用作非IDE的程序时,这些内容就不那么合理了。虽然所有的源代码都是公开的,但是要找到这些修改的地方仍然不是那么的容易。所以,在Eclipse 3,设计者重构了API使得用户界面的这些部分可以通过公有的API来控制。

到目前为止,Eclipse 3引入了一个全新的WorkbenchAdvisor类和一组*Configurer接口。其中对RCP开发人员最重要的类就是WorkbenchAdvisor。你可以在你的RCP应用中继承WorkbenchAdvisor,重写一些方法来设置任何你需要的选项。在第一部分,我们实现了一个简单方法,getInitialWindowPerspectiveId,它是用来返回一个应用唯一的透视图(视图,编辑器,和菜单)。

在下一节,我们来看看其他的一些advisor方法。如果你想看第二部分的代码,可以在这里下载它们

下面,我们就先来对Application,Workbench,和Workbench Window 作 一个清晰的了解。

Applications, Workbenches, 和 Workbench Windows

Application是一个你创建的作为RCP主程序的类。你可以认为它是程序的控制器。就象Model 2架构中的控制器一样,它很短小,并且在不同的项目中都差不多。它所做的就是创建一个Workbench,并交给Workbench一个Workbench Advisor。

对你来说,Workbench是作为RCP框架的一部分被声明和维护的。一个Application只有一个Workbench,但是一个Workbench可以有超过一个可见的顶层Workbench Window。例如,在Eclipse IDE中,当你第一次启动Eclipse时,你会看到一个Workbench Window,但是如果你选择Window > New Window,就会出现第二个窗口,这样就有两个Workbench Window,而还是单独一个Workbench。

图1显示了Application,Workbench,以及Workbench Window之间的关系。

图1 一个RCP程序有一个你定义的Application类,和一个框架提供的Workbench类。一般只有一个Workbench Window,但是框架支持多个Workbench Window。

好,现在我们就来试试改变一下Workbench Window的样子。

定制 Workbench Window

第一部分的那个例子含有状态栏,工具栏以及其他的一些可视元素,但是这些并没有被使用。我们可以争辩说这些元素在缺省条件下应该不显示,但是由于某种原因,情况并不是这样,所以如果你不想要它们,你不得不自己把它们关掉。并且在那个例子中窗口没有标题,大小也比需要的大很多。设置这些内容的一个合适的地方就是WorkbenchAdvisorpreWindowOpen方法,请看下面代码1。

代码 1. preWindowOpen 例子.

    public void preWindowOpen(IWorkbenchWindowConfigurer configurer) {
        super.preWindowOpen(configurer);
        configurer.setInitialSize(new Point(400, 300));
        configurer.setShowCoolBar(false);
        configurer.setShowStatusLine(false);
        configurer.setTitle("Hello, RCP");
    }

注意Configure接口(这里就是IWorkbenchWindowConfigurer)是如何被传递给advisor方法的。你可以调用Configure接口中的方法来设置选项。本教程不会详细介绍这些接口,需要的话你可以参考它们的Javadoc。图2显示了最后的效果。

 

图 2. 带有标题的Workbench window。其他没有用到的控件被关闭了,标题是使用WorkbenchAdvisor的preWindowOpen事件设置的。

深入WorkbenchAdvisor类

既然RCP是新的技术,文档还不多,我们先来看一下有关WorkbenchAdvisor类的背景信息。Platform在Workbench生命周期中的各个点调用这个类的方法。这个类同时还在事件循环中提供了一种处理异常的方法,以及向Workbench提供诸如缺省透视图这样的重要参数。首先我们来看一下Workbench生命周期中的事件。

Note: 为什么WorkbenchAdvisor不是一个接口?你可能注意到WorkbenchAdvisor是一个虚类。对于大多数情况,Eclipse API使用接口,避免使用抽象类,和实现这些接口的基类。在这里,开发者打算使用总是由RCP应用实现的WorkbenchAdvisor,基类不包含任何重要功能,并且在今后会添加新的方法(这些在使用接口的情况下是比较困难的)。所以这是一个经过考虑的设计选择。更多的内容可以参考教程后面有关Java API的文章。

生命周期事件

Workbench只有一个,虽然你可以打开不止一个Workbench Window,但一般,Workbench Window也只有一个。图3显示了在Workbench和Workbench Window生命周期中最重要的事件。表1显示你在WorkbenchAdvisor子类中可以重写来处理Workbench生命周期事件的所有方法。表2显示那些处理Workbench Window生命周期事件的方法。

 

图 3. Workbench和Workbench Window生命周期中的重要事件。这些事件在WorkbenchAdvisor中都有相应的方法,Platform调用这些方法从而执行你的定制代码。

表 1. Workbench 生命周期事件处理方法,它们定义在org.eclipse.ui.application.WorkbenchAdvisor中。

方法 描述 参数
initialize

第一个被调用,用来初始化,比如解析命令行,注册适配器,声明图像等时。

IWorkbenchConfigurer
preStartup

在初始化结束,但是在第一个窗口打开前调用。可以被用来设置一些选项来影响初始打开的编辑器和视图。

 
postStartup

在所有窗口已经被打开或恢复后,但是在事件循环开始前调用。它可以被用来启动自动处理器,打开提示或其他窗口。

 
preShutdown

在事件循环结束后,但在任何窗口被关闭前调用。

 
postShutdown

在关闭Workbench过程中,所有窗口被关闭后调用。它可以被用来存储当前的应用状态和清理任何由initialize创建的东西。

 

表 2. Workbench window 生命周期事件处理方法,它们定义在org.eclipse.ui.application.WorkbenchAdvisor.中。

方法 描述 参数
preWindowOpen

在Workbench Window的构造器中调用。可以使用这个方法来指定窗口是否有菜单栏。然而,窗口的widget还没有创建,因此在这个方法中不能引用它们。

IWorkbenchWindowConfigurer
fillActionBars

紧接着preWindowOpen后调用。在这个方法里,你可以设置任何代码实现的菜单,工具栏。因为参数flags,这可能是这里最复杂的一个方法。注意:这个方法接受一个Workbench Window实例,而不是configurer。

IWorkbenchWindow, IActionBarConfigurer, flags
postWindowRestore

当一个窗口从保存的状态恢复时,但在打开前,被调用。

IWorkbenchWindowConfigurer
postWindowCreate

在窗口从保存状态恢复,或从scratch中创建后,但在打开前,被调用。

IWorkbenchWindowConfigurer
openIntro

在窗口打开前一刻被调用,它用来创建introduction组件(如果有的话)。

IWorkbenchWindowConfigurer
postWindowOpen

紧接着Workbench Window被打开后调用。它被用来组装窗口的widget,例如设置标题或修改它的大小。

IWorkbenchWindowConfigurer
preWindowShellClose

在Workbench Window被关闭前调用(从技术上来说,是在它的shell被关闭前)。这是唯一能够终止关闭动作的方法,所以,它可以用来显示“你确定吗”这样的对话框。

IWorkbenchWindowConfigurer
postWindowClose

在Workbench Window关闭后调用。它被用来清理任何由preWindowOpen创建的资源。

IWorkbenchWindowConfigurer

事件处理方法

事件循环是在Workbench生命周期中运行事件最长的代码。它处理所有的用户输入,并将它们派发到正确的处理方法中。RCP提供了一组方法来处理应用崩溃以及在空闲时间调用(见表3)。

表 3. org.eclipse.ui.application.WorkbenchAdvisor中定义的事件处理方法

方法 描述 参数
eventLoopException 当事件循环中出现一个unchecked异常时调用。缺省实现是记录这个错误。
Throwable
eventLoopIdle

当事件循环没有什么需要做的时候调用。

Display

信息获取方法

接下来,你可以实现一些方法供Platform调用,使得Platform获取关于你应用的信息(见表4)。最重要的(并且也是唯一必需的)是getInitialWindowPerspectiveId。我们在第一部分中使用它来返回起始透视图的ID。

表 4. org.eclipse.ui.application.WorkbenchAdvisor定义的信息请求

方法 描述 参数
getDefaultPageInput

返回新的Workbench页面的缺省输入,缺省值是null。

 
getInitialWindowPerspectiveId

返回新创建的Workbench Window的初始透视图。这个方法必须提供。

 
getMainPreferencePageId

返回第一个显示的首选参数页。缺省是null,这意味着首选参数页按字母顺序排序。

 
isApplicationMenu

返回是否是应用菜单。这和OLE相关,详细参考Javadoc。

IWorkbenchWindowConfigurer, String

高级配置

上面的WorkbenchAdvisor事件对大多数应用来说是足够了,但是在某些情况,RCP又提供了两个方法来控制你的应用窗口和控件如何被创建。它们被列在表5,但是我觉得很多程序不需要用到这些。

表 5. org.eclipse.ui.application.WorkbenchAdvisor提供的高级方法

方法 描述 参数
createWindowContents

创建一个窗口的内容。重写这个方法来定义自定义的内容和布局。

IWorkbenchWindowConfigurer, Shell
openWindows

在启动时打开所有Workbench Window。缺省实现会恢复前面存储的Workbench状态。

 

准备国际化

国际化(缩写I18N)允许你的应用可以面向更广泛的市场。第一步很简单,将显示给用户的文本信息从你的代码提取出来,放置到一个标准格式的properties文件中。即使你没有打算使你的代码支持多种语言,将文本信息和代码分离可以使你更容易地检查拼写错误,语法,以及措词。

在Eclipse中,并没有什么魔法来处理文本信息,你仅仅使用普通的Java的resource bundle机制。Eclipse IDE提供了一个不错的Externalization的向导来使工作变得容易些。你可以看参考部分的文章来详细了解如何使用这个向导。

当你在一段新的代码时,你常常会写固定的文本信息以便这段代码能工作。例如,我们有

	configurer.setTitle("Hello, RCP");

一旦你让这段代码工作后,你应该养成习惯使用Externalization向导将这些字符串提取出来。在项目上点击鼠标右键,选择Source > Find Strings to Externalize...。任何需要注意的源文件会被列出来。选择一个,按按钮Externalize...打开Externalization向导。在那儿,向导会将你的代码转换成一个resoure bundle引用。或者,你可以右键点击一个源文件,选择Source > Externalize Strings...。当你完成,你的代码看起来象下面那样:

	configurer.setTitle(Messages.getString("Hello_RCP")); //$NON-NLS-1$

字符串$NON-NLS-1$用来提示编译器和Externalization向导,这一行的第一个字符串是一个标签或关键字,不需要本地化。

当然你会有一个标准格式的.properties文件,它包含了你所有文本信息的键和值。在示例程序中,你会发现一个RcpTutorial.properties的文件,它包含了

Hello_RCP=Hello, RCP

最后,向导会建立一个封装Java resource bundle的类来装载.properties file,并查找值。

Tip: 为了完成替代,可以使用标准的java.text.MessageFormat类。它的format()方法类似于C语言的sprintf函数,除了不是使用由百分号来控制格式,而是用包含序号的花括号对。这里有一个来自例子plug-in的XMLStructureCreator类的例子:

	bodynode.setName(MessageFormat.format("{0} ({1})",
		new String[] {XMLCompareMessages.getString("XMLStructureCreator.body"),
		Integer.toString(fcurrentParent.bodies)})); //$NON-NLS-2$ //$NON-NLS-1$

这并不是一个好的例子,因为格式字符串本身(译,这里指的是“{0} ({1})”)也应该是定义在一个消息文件中。然而,用于其他程序的消息(命令,关键字,脚本,等)不应该存在在消息文件中。

为了防止一行变得太长,你可能需要创建帮助方法。帮助方法的例子可以看org.eclipse.internal.runtime.Policy

结论

在本教程的第二部分中,我们看了RCP重构后的新API,这些API允许你开放自定义外观的客户端Java程序。下一部分将深入讨论定义和建立菜单和工具栏。所有的例子代码可以在这里得到。你可以使用Eclipse的内置CVS客户端下载源程序。

Rich Client 教程 第三部分

Rich Client Platform (RCP)使你可以从Eclipse中选择功能用在你的应用中。本教程的第一和第二部分介绍了平台以及它所提供的部分配置类。第三部分讨论如何增加功能,例如菜单,视图,帮助文件等。

(译,本教材适用于Eclipse 3.0,并在不久为Eclipse 3.1作更新)

作者 Ed Burnette, SAS
译者 Cliff Liang,BeniSoft
2004年7月28日


简介

前面两个部分我们讨论了怎样从平台挪走一些东西-关掉工具条,去掉菜单等等。从这部分开始,我们就来看看怎么把这些东西放回去. 你可以从Eclipse 项目下载教程中的所有源代码。

视图

我们先从视图开始。Eclipse 的 Plug-in 开发环境提供一套很好的extension模板,使你可以很快地写出例子视图,编辑器,菜单和其他组件。遗憾的是,对于RCP开发来讲这些代码几乎没什么用处,因为这些代码引入了对IDE , 资源包和plug-in等的依赖。

Tip: 总的来说,规则是涉及资源的任何东西都不是给RCP开发者使用的,因为其使用特别的代码以及依赖所在的workspace。因此,如果你看到org.eclipse.core.resources plug-in在你所依赖的列表里面,或者看到从那个包导入了某些类,你可能就已经做错了。虽然这不是一条固定和快速的判断标准,但是所有的资源都应该看成为Rich Client Platdform的可选 部分.。

如果要不使用模板创建一个视图,你可以使用 plug-in 的Manifest编辑器提供的基于schema的extension向导(Extensions pane > Add > Generic Wizards > Schema-based Extensions)或者在Source Pane中编辑XML文件。采用以上任何一种方式,你都可以得到类似这样的extension XML:

<extension point="org.eclipse.ui.views"> <category name="SampleCategory" #1 id="org.eclipse.ui.tutorials.rcp.part3.viewCategory"> </category> <view name="Sample" icon="icons/sample.gif" category="org.eclipse.ui.tutorials.rcp.part3.viewCategory" #2 class="org.eclipse.ui.tutorials.rcp.part3.views.SampleView" id="org.eclipse.ui.tutorials.rcp.part3.views.SampleView"> </view> </extension>

视图的category (#1) 使你可以在Show Views对话框中组织你的视图。class属性(#2)所指定的类 继承了 ViewPart 抽象类。如下所示:

	public class SampleView extends ViewPart {
#1	    public static final String ID_VIEW =
	        "org.eclipse.ui.tutorials.rcp.part3.views.SampleView"; //$NON-NLS-1$
	
	    private TableViewer viewer;
	
	    public SampleView() {
	    }
	
#2	    public void createPartControl(Composite parent) {
	        viewer =
	            new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
	        viewer.setContentProvider(new ViewContentProvider());
	        viewer.setLabelProvider(new ViewLabelProvider());
	        viewer.setInput(this);
	    }
	
	    public void setFocus() {
	        viewer.getControl().setFocus();
	    }
	}

定义一个以 ID_开头的常量 (#1) 是Eclipse源代码中经常使用的一种常规方式。这里,我们还在plug-in的manifest中使用它。它还在将来需要引用该视图时使用.

这个类最重要的部分是createPartControl 方法 (#2)。在这里,你可以创建用于组成视图的JFace或者SWT控件。源代码的其它部分可以在例子项目中找到。视图编程超出了本教程的范围,但你可以在参考部分找到更多相关信息。

添加透视图

如果你现在运行代码,你不会看到任何不同的东西。为什么呢?因为你的新视图在被加入当前透视图之前不会显示。你可以通过代码或者为org.eclipse.ui.perspectiveExtensions实现extension添加视图。我们将使用前一种方式,因为这种方式更加灵活。为此,我们回过头去看一下刚才定义的RcpPerspective类并且做一些修改:

	public class RcpPerspective implements IPerspectiveFactory {
#1	    public static final String ID_PERSPECTIVE =
	        "org.eclipse.ui.tutorials.rcp.part3.RcpPerspective"; //$NON-NLS-1$
	
	    public RcpPerspective() {
	    }
	
	    public void createInitialLayout(IPageLayout layout) {
#2	        layout.setEditorAreaVisible(false);
#3	        layout.addView(
	            SampleView.ID_VIEW,
	            IPageLayout.TOP,
	            IPageLayout.RATIO_MAX,
	            IPageLayout.ID_EDITOR_AREA);
#4	        layout.addPerspectiveShortcut(ID_PERSPECTIVE);
#5	        layout.addShowViewShortcut(SampleView.ID_VIEW);
	    }
	}

注意:

#1

再次强调,养成习惯把所有的字符串定义成常量,尤其是id。

#2

平台支持编辑器,但是我们在这个例子中不使用它。因此,你需要把编辑器区域关掉,这样就不会在你的Workbench窗口中看到一个大块空白。

#3

这是这个类最重要的部分。它把视图加到透视图,视图缺省是可见的。位置参数定义了这个视图在编辑器区域上方,并且占Workbench Window的全部大小。这看起来可能有点奇怪,因为我们没有编辑器区域,但编辑器区域还是存在的,虽然它不可见。当你给应用添加多个视图时,你可以在这里定义缺省的视图堆叠和布局方式。

#4

如果你实现PERSPECTIVES_SHORTLIST菜单条目的话(参考例子程序),这个方法使透视图出现在短列表当中。如果没有这个方法,透视图只会在用户选择Window > Open Perspective > Other((或者你的应用中其他类似菜单路径)的时候出现在长列表中。

#5

同样,仅用于视图。

Tip: 如果要在用户下次打开你的应用时记住上次的布局和窗口大小,在WorkbenchAdvisorinitialize方法里加上configurer.setSaveAndRestore(true);。你可以在例子项目中找到一个例子。

固定视图

缺省情况下,视图是可以移动,改变大小,并且是可以关闭的。但是你常常不需要这种灵活性。例如,如果你正在为普通用户写一个订单录入应用,你不想回答如果用户不小心关闭了表格视图该怎么办这样的问题。为此,Eclipse 3.0引入了固定透视图和固定视图的概念。

固定视图就是不能被关闭的视图。视图的标题栏没有关闭按钮。为了创建这样的视图,你需要使用IPageLayout定义的setFixed()方法。

一个更好的办法就是使用固定透视图。固定透视图中,所有的视图都是固定的,此外,它还禁止它们移动和改变大小。要使用固定透视图,只要简单地在透视图定义中设置属性fixed="true",例如:

    <extension
        point="org.eclipse.ui.perspectives">
        <perspective
            name="%perspectiveName"
            icon="icons/sample.gif"
            fixed="true"
            class="org.eclipse.ui.tutorials.rcp.part3.RcpPerspective"
            id="org.eclipse.ui.tutorials.rcp.part3.RcpPerspective">
        </perspective>
    </extension>

使用固定透视图并关闭快捷栏,你可以使用户始终使用这个透视图,并且完全向用户隐藏它们。

菜单

RCP的一个需求就是允许你配置所有的菜单。在一个RCP应用添加菜单有两个方法:

  • WorkbenchAdvisor.fillActionBars
  • org.eclipse.ui.actionSets in the plug-in manifest

fillActionBars是引用内建Workbench action的唯一方式。其他action都可以通过actionSets这个extension point来实现。这两个方法我们都将在这里演示。虽然例子应用没有使用工具栏,但是它们和菜单非常类似。

首先,我们来看看fillActionBars

	public void fillActionBars(
	    IWorkbenchWindow window,
	    IActionBarConfigurer configurer,
	    int flags) {
	    super.fillActionBars(window, configurer, flags);
#1         if ((flags & FILL_MENU_BAR) != 0) {
	        fillMenuBar(window, configurer);
	    }
	}

fillActionBars使用参数flags(#1)来指定代码应该做什么。在菜单栏,工具栏,状态栏都有flag位,甚至还有一个位用来指定它是否是用于preference对话框的伪请求(FILL_PROXY)。我在用这些flag时有过糟糕的经历,所有例子代码调用一个帮助方法fillMenuBar来做实际的菜单填充。下面是fillMenuBar的代码。

	private void fillMenuBar(
	    IWorkbenchWindow window,
	    IActionBarConfigurer configurer) {
	    IMenuManager menuBar = configurer.getMenuManager();
	    menuBar.add(createFileMenu(window));
	    menuBar.add(createEditMenu(window));
	    menuBar.add(createWindowMenu(window));
	    menuBar.add(createHelpMenu(window));
	}

这个例子中,我们要建立四个顶层菜单:File,Edit,Window,和Help。它们对于于Eclipse IDE中相同名字的菜单。对于一个实际应用,你可能不需要所有的,或者你想用别的名字。看下面的图1。

图 1. Workbench的菜单栏在WorkbenchAdvisorfillActionBars方法中定义,并且添加所有扩展org.eclipse.ui.actionSets的plug-in的manifest中定义的菜单。

这些方法的代码可以在例子项目找到。我们来仔细看看其中之一,File菜单:

	private MenuManager createFileMenu(IWorkbenchWindow window) {
#1	    MenuManager menu = new MenuManager(Messages.getString("File"), //$NON-NLS-1$
	        IWorkbenchActionConstants.M_FILE);
#2	    menu.add(new GroupMarker(IWorkbenchActionConstants.FILE_START));
	    menu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
#3	    menu.add(ActionFactory.QUIT.create(window));
	    menu.add(new GroupMarker(IWorkbenchActionConstants.FILE_END));
	    return menu;
	}

所有的菜单都以同样的方式工作。首先,你创建一个为菜单MenuManager (#1) ,它使用一个消息文件来查找实际用来显示给用户的名称。然后你添加所有的菜单项,并返回MenuManager。关于更多定义视图和菜单的信息,你可以看参考部分。接下来,你创建一个占位符 (#2),在那儿可以其他plug-in可以添加额外的菜单项,以及一个由Workbench提供的动作:Quit action (#3)。ActionFactoryContributionItemFactory的Javadoc定义了所有Workbench支持的action。

Note: 当你在Eclipse IDE中完成象上面这样的工作,你可以使用大量用于菜单和工具栏的标准占位符名。使用这些预定义的组,为Eclipse IDE设计的菜单和工具栏也可以用于你的RCP应用。这些内容在IWorkbenchActionConstants的Javadoc中可以找到,但是没有有关它们顺序的说明。这个教程的例子代码是根据Eclipse IDE使用的IDEWorkbenchAdvisor类的Javadoc创建的。

帮助

RCP一个很cool的功能就是帮助系统。你只要提供XML格式的目录结够,以及HTML格式的内容,就可以提供给用户一个可以查找的帮助系统,整个过程你不需要任何代码。首先,你在你的plug-in的manifest中添加一个extension,就象下面一样:

	<extension
	      point="org.eclipse.help.toc">
	   <toc
	         file="book.xml"
	         primary="true">
	   </toc>
	</extension>

然后你创建一个目录文件(这个例子中是book.xml)定义帮助标题的层次结构。不是所有的标题都必需在这个文件中,但是鼓励这样做。这儿有一个例子:

	<toc label="RCP Help Sample"  topic="html/book.html">
	   <topic label="Overview" href="html/overview.html"/>
	</toc>

参考部分提供了更多撰写,组织帮助文件,包括国际化的资料。

当你调试或部署一个包含帮助的RCP应用时,你需要包括几个和帮助相关的plug-in。这儿是目前这些plug-in的列表(可能在今后的版本会有所改变)。

  • org.apache.ant
  • org.apache.lucene
  • org.eclipse.help.appserver
  • org.eclipse.help.base
  • org.eclipse.help.ui
  • org.eclipse.help.webapp
  • org.eclipse.tomcat

在例子代码中,你可以看到createHelpMenu()用来添加Help Contents的action到你的Help菜单。当你选择它时,这个action会弹出一个帮助浏览器,就象下面图2。

图 2. Rich Client Platform提供了功能丰富的在线帮助框架。你所需要做的就是提供帮助的内容。

Build.properties

当你添加HTML文件,图标,帮助目录等资源到plug-in时,别忘了更新你的build.properties文件,添加这些在plug-in运行时需要的文件,目录。这儿是一个更新后的build.properties,它包含例子中需要的所有文件。

bin.includes = plugin.xml,/
               *.jar,/
               part3.jar,/
               plugin.properties,/
               book.xml,/
               html/,/
               icons/
source.part3.jar = src/

结束语

在这部分中,我们创建一个RCP应用,并添加了一个简单的视图,一些菜单,和帮助文件。你可以用这个例子作为你自己项目的参考。这部分的所有代码可以在这里找到。你可以使用Eclipse内置的CVS客户端来下载它们。

贡献你!你已经可以开放自己Rich Client Platform应用。你可以看看下面的参考信息,站点和邮件列表。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
发现网上关于vbrichclient教程比较少,但这个实在是好东西,实用性,稳定性都比VB自带的winsock好的多,多客户端不用winsock控件数组。 也不用在各窗体上放winsock,直接在模块中就能实现收发 下面直接上代码,窗体和文本钮、按钮大家自行拖放。要用到VB自带隐藏函数varptr()取内存指针(VbMsdn中没有这个函数,实际上很简单^^)。 VbRichClient5.0.38中包含sqlite3.9支持 上面共享中也包含VbRichClient5.0.38支持库 VbRichClient代替winsock 主要使用 cTCPServer cTCPClient cUDP '--------------------------------------------------------------------- '服务器端,代码最简化,要实现多客户端只要用数组存hsocket就可以 Option Explicit Dim WithEvents sv As cTCPServer Dim WithEvents udp1 As cUDP Dim cHsocket& Private Sub Form_Load() Set sv = New cTCPServer sv.Listen sv.GetHost("127.0.0.1"), 35912 Debug.Print sv.GetHost("") Set udp1 = New cUDP udp1.Bind "127.0.0.1", 5616 End Sub Private Sub sv_DataArrival(ByVal hSocket As Long, ByVal BytesTotal As Long, ByVal FirstBufferAfterOverflow As Boolean) Dim d() As Byte, s$ ReDim d(BytesTotal - 1) sv.GetData hSocket, VarPtr(d(0)), BytesTotal '★★关键代码 s = d Text2.Text = Text2.Text & s & vbCrLf Debug.Print "收到:" & BytesTotal End Sub Private Sub sv_TCPAccepted(ByVal hSocket As Long) cHsocket = hSocket Text1.Text = Text1.Text & sv.GetPeerHostIPAndPort(hSocket) & vbCrLf End Sub Private Sub sv_TCPDisConnect(ByVal hSocket As Long) Text3.Text = Text3.Text & sv.GetPeerHostIPAndPort(hSocket) & vbCrLf End Sub Private Sub udp1_NewDatagram(ByVal BytesTotal As Long, ByVal FirstBufferAfterOverflow As Boolean) Dim d() As Byte, s$ ReDim d(BytesTotal - 1) udp1.GetData VarPtr(d(0)), BytesTotal s = d Text2.Text = Text2.Text & s & vbCrLf End Sub '------------------------------------------------------- '客户端 Option Explicit Dim WithEvents cl As cTCPClient Dim WithEvents udp1 As cUDP Dim cid& Private Sub Command1_Click() cid = cl.Connect("QgB1", 35912) End Sub Private Sub Command2_Click() cl.Disconnect cid End Sub Private Sub Command3_Click() Dim b() As Byte b = Text1.Text cl.SendData cid, VarPtr(b(0)), UBound(b) + 1 End Sub Private Sub Command4_Click() Dim d() As Byte, s$ s = "yessss" d = s udp1.RemoteIP = "127.0.0.1" udp1.RemotePort = 5616 u

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值