摘自:http://book.csdn.net/bookfiles/493/10049317083.shtml
从本章开始,将带领大家进入激动人心的Eclipse RCP开发之旅。本章先将经费测算系统的架子搭建起来,例如菜单、工具栏、主控界面等等,至于系统各功能的实现细节,在随后的章节中将层层剥开。为了节省篇幅,从本章开始,对于大量需要导入的类,在程序代码中将予以省略。
本章将主要学习到以下技术实现:
l 创建RCP项目。
l 定制开发平台和目标平台。
l 定制窗口属性。
l 添加菜单和工具栏。
l 实现主界面透视图、视图。
l 实现系统托盘。
l 定时自动显示托盘气泡提示文本。
l 图片的缓冲处理。
l 品牌化应用程序。
5.1 新建RCP项目
为了方便后面工作,可先将以前所做的test项目删除。在test项目上点击鼠标右键,选择【Delete】,在弹出的“Confirm Project Delete”对话框中单击【Yes】按钮即可。如果要彻底删除,请选择“Also delete contents under ‘c:"jfcs_workspace"test’”。
在新建RCP项目之前,先设置一下整个Eclipse系统默认文件输出组织方式。选择主菜单【Window】→【Preferences…】,在弹出的“Preferences”对话框中展开Java,选中Build Path,在Source and output folder下单选Folders,再单击【Apply】按钮(一定要单击此按钮,而不是直接单击【OK】按钮),如图5-1所示。这样设置的目的是将源文件和编译后的class目标文件分开存放,以方便管理。
图5-1 项目输出路径设置
5.1.1 创建经费测算项目
创建RCP项目时,Eclipse提供了向导方式,并内置了3种RCP模板,整个工作简单而又轻松,具体步骤如下:
(1)单击鼠标右键,选择【New】→【Project…】,在弹出的对话框中选择【Plug-in Project】,单击【Next】按钮,在Project name后输入项目名称cn.edu.jfcs。项目名称习惯上命名为公司域名+产品名称的倒序,这样可以比较好的避免与他人产品名称重复。例如:cn.edu.hust.gzgl,表示华中科技大学工资管理系统项目。
单击【Next】按钮,弹出如图5-2所示的对话框,要求用户指定ID、Version、Name等信息。Plug-in Provider可以输入作者名称或者公司名称。Classpath要求指定类文件夹名称,一般针对插件项目,对于RCP项目来说,可以不指定。不需要勾选Plug-in Options下的“Generate an activator, a Java class that controls the plug-in’s life cycle”,对于RCP来说并不需要生成一个激活器类来控制插件的生命周期。选中Rich Client Application中的Yes。
图5-2 插件配置
(2)单击【Next】按钮,Eclipse提供了3种RCP模板以供选择。选中“RCP application with an intro”模板。该模板启动时会带有欢迎画面。
(3)单击【Next】按钮,弹出“New RCP Project with an intro”对话框。将Product Name修改成jfcs,其他不需要修改。单击【Finish】按钮,项目创建完成。
现在修改一下项目的包名。展开项目src文件夹,向导默认创建的包名为cn.edu.jfcs.intro,这个包名的含义有些含混不清,并不是希望的结果。将该包名修改成更有意义的cn.edu.jfcs.app似乎更好。修改包名需要用到Eclipse的重构(Refactor)功能。
重构简单说来就是将程序中的元素,例如某个类,重新命名,并自动更新相关的应用。设想一下,如果希望将某个类重新命名,但这个类可能在很多地方引用,如果没有重构功能,得到全部类中搜寻,这项工作不但费力而且痛苦不堪,关键是辛苦半天可能还有遗漏!Eclipse的重构功能受到了开发人员的热烈欢迎,一个常用的例子是Rename重构,Rename重构可以对属性、变量、类以及接口等重新命名,并自动更改全部引用而不会遗漏。实际上Rename重构只是Eclipse重构的一种,Eclipse重构还可以实现将一个类中的方法或者属性移到子类或者父类中,或者改变类内部的代码,例如将某个方法中的代码抽取出来变成一个独立的方法。善用重构功能,可以减轻一定的编程工作量。
在包名cn.edu.jfcs.intro上单击鼠标右键,选择【Refactor】→【Rename…】,弹出“Rename Package”对话框,在New name后的文本框中输入新包名cn.edu.jfcs.app,单击【OK】按钮即可。
现在可以试运行经费测算程序,体验一下RCP程序。单击如图5-3所示的项目Overview概览视图中的“Launch an Eclipse application”,将首先弹出splash闪屏画面,然后显示如图5-4所示的系统主界面。该界面自带了Help菜单,并有一个简单的Welcome欢迎界面。
图5-3 项目概览视图 图5-4 项目运行主界面
项目的运行实际上还有更快捷的方式。单击如图5-5所示的工具栏Run 图标按钮,即可运行jfcs项目。注意到,该运行图标按钮的提示文本是“Run Eclipse Application”,换成有意义的提示更好。因为一旦项目很多,工具按钮的提示文本就可能使人不得要领。选择系统菜单的【Run】→【Run…】,在弹出对话框的Name文本框中输入“jfcs”,单击【Apply】按钮,再单击【Close】。现在鼠标指向Run图标按钮,提示文本变为“Run jfcs”。
图5-5 工具栏Run图标按钮
5.1.2 项目的组织结构
在第1章曾经讨论到,Eclipse RCP基于组件架构,该组件架构的最基本单元被称之为插件(Plug-in),插件则通过插件扩展点(Extension point)定义。在Eclipse里面,“万物皆插件”。所谓的RCP,不过是插件及其支撑内核的集合而已,只不过最后需要打包成产品发布。开发者只需要在Eclipse内核基础上,定义并实现一个一个的插件,就可以组装成RCP。所以,在前面创建经费测算项目时,选择“Plug-in Project”,也就不足为怪了。也就是说,高校经费测算项目实际上就是一个大的插件!你可以认为Eclipse是花瓶,插件是一朵一朵的花,就看你需要向花瓶中插入哪些花了。图5-6是项目组织结构。
图5-6 项目组织结构
还记得前面项目运行时出现的闪屏画面吧,该画面就是由splash.bmp文件指定的。闪屏图片必须是bmp格式的图片,一旦删除该文件,或者更改文件名称,将不会出现闪屏画面。另外,图5-6中的introContent.xml、content文件夹用于定制程序启动主界面中的Welcome欢迎画面(见图5-4)。可以按照自己的需要修改欢迎画面,关于闪屏画面的制作将在第7章详细说明。下面认识一下项目组织结构的各个部分。
1.src
src文件夹存放了项目的源程序,那么编译后的class文件在哪儿?项目组织结构中并没有列出,实际保存在bin文件夹下。回想一下,在本章一开始就设置了系统默认文件输出组织方式(见图5-1)。今后操作过程中应该知道在哪里找源代码,在哪里找class文件。
2.JRE System Library
该文件夹存放系统类库文件。Eclipse已经自动帮你导入了相关类库,你可以展开看看项目需要哪些类库。
3.Plug-in Dependences
该文件夹存放插件依赖类库文件。可以展开看看当前项目需要哪些插件才能正常运行。不过,要更为直观地查看插件依赖,请双击build.properties文件,在打开的Overview概览视图中再单击Dependencies页,如图5-7所示。可以看到现在的项目需要org.eclipse.ui.intro、org.eclipse.core.runtime、org.eclipse.ui这三个核心插件。这三个插件实际上还需要依赖其他插件,怎么查看依赖关系?单击“Dependency Analysis”插件依赖性分析,再单击“Show the plug-in dependency hierarchy”,如图5-8,Eclipse会给出非常详细的插件依赖关系说明。
图5-7 插件依赖项 图5-8 插件依赖关系明细
4.MANIFEST.MF
MANIFEST.MF文件对当前插件(项目)进行描述,并可定义与其他插件的关系,也就是插件的原数据。该文件一般不需要修改。双击该文件可以查看具体情况,类似于图5-9中所示。
图5-9 MANIFEST.MF
在MANIFEST.MF中定义了版本、插件的ID号、插件的依赖项(Require-Bundle)等等。singleton为true表示该插件项目只能有唯一版本,该参数是为了解决同一名称插件的多版本并存问题。
Eclipse-LazyStart项比较有意思。Eclipse-LazyStart用于指定当前插件的启动方式,具体说就是当插件中的类或者资源被访问时,该插件是否自动启动。Eclipse-LazyStart允许Eclipse以一种“惰激活”(懒加载)的方式启动插件,即插件被访问时才启动,不访问不启动。这岂不很妙,RCP应用程序就可以在启动时只需要加载尽可能少的必需插件。因此,设置为true可以提升启动速度。
5.build.properties
build.properties用来配置插件的编译信息,即定义与项目打包时(构建)相关的属性定义。可以利用该文件,将项目打包运行时所需要的部件或插件包含进来,如下所示形式:
source.. = src/
output.. = bin/
bin.includes = plugin.xml,"
META-INF/,"
.,"
content/,"
splash.bmp,"
introContent.xml
前面两句指定项目打包时源文件和class文件的输出文件夹,bin.includes则指定了项目打包时所包含的文件夹或者文件,例如闪屏图片splash.bmp。通常情况下项目总是有很多修饰图标或图片,一般放置在项目的icons文件夹下。如果没有该文件夹,输出产品后在需要显示图标的地方就会显示Eclipse默认的图标(红盒子)。解决方法当然很简单,可以在build.properties最末尾加入“icons/”。如果是在中间加入,则应该是“icons/,"”形式。
6.plugin.xml
前文中已经简单提到插件是通过扩展点(Extension point)来定义的。扩展点是插件提供服务的入口,有点类似于Java 中的接口。例如宾馆服务员张三(插件)为顾客李四(插件)提供服务,张三定义好了一个服务契约扩展点,这样一来李四通过扩展点就知道如何获取服务、可以有哪些服务了。Eclipse采用了完全开放的扩展点机制,开发人员可以在任何觉得可能被扩展的地方定义扩展点,以方便其他人扩展系统的功能,例如添加工具栏、菜单等等。这样一来,系统的开放程度主要取决于扩展点多少了。扩展点信息保存在plugin.xml文件中。
下面是一个菜单的扩展点定义。
<extension
point="org.eclipse.ui.actionSets">
<actionSet
id="cn.edu.jfcs.actionSet"
label="Sample Action Set"
visible="true">
<menu
id="sampleMenu"
label="扩展点测试">
<separator name="sampleGroup"/>
</menu>
<action
class="cn.edu.jfcs.actions.SampleAction"
icon="icons/sample.gif"
id="cn.edu.jfcs.actions.SampleAction"
label="单击试试"
menubarPath="sampleMenu/sampleGroup"
toolbarPath="sampleGroup"/>
</actionSet>
</extension>
l org.eclipse.ui.actionSets是工具栏或者菜单的操作集扩展点。
l <actionSet>项定义了操作集的标识、名称和可视性。
l <menu>项定义了菜单的标识、名称。
l <action>项定义了下拉菜单项的类名(没有编写,选中时执行的任务)、图标、标识、名称、路径等等。
将上述代码复制粘贴到plugin.xml文件</plugin>的前面,保存并运行看看!现在多了一个【扩展点测试】菜单,单击其下的子菜单项【单击试试】,将弹出一个“Information”对话框,提示“The chosen operation is not currently available.”(选择的操作当前不可用)。这是因为cn.edu.jfcs.actions.SampleAction还没有编写。试验完毕后,记得将该扩展点从plugin.xml文件中删除。当然Eclipse的扩展点较多,读者可以参考Eclipse自带的帮助或者其他书籍进行学习。
5.1.3 RCP基本框架
一个基本的RCP应用程序已经搭建起来,尽管还非常稚嫩,却已经初具雏形。探究一下RCP的基本框架对于理解RCP大有好处。从前面图5-6可以看出,Eclipse已经自动生成了Application.java、ApplicationActionBarAdvisor.java、ApplicationWorkbenchAdvisor.java、ApplicationWorkbench- WindowAdvisor.java、Perspective.java这5个类文件。有必要对这5个文件进行分析,以便更深刻地理解RCP的基本框架。在分析之前,先来简单理解一下几个基本概念。
1.基本概念
(1)Display
应用程序一般只需要一个Display对象,该对象实际上是一个SWT对象,代表了底层图形系统的实现。Display的主要任务是事件处理,它负责从操作系统的事件队列中读取事件,传递给RCP的事件监听器以便完成具体的任务。需要注意的是,Display对象不代表应用程序窗口的任何可视控件,在应用程序主窗口打开之前,Display是不可获得的。应用程序主窗口打开之后,才可以通过一个被称作Shell的对象获得。Display对象的获得方法如下。
Display display = new Display();
或者:Display display=Display.getCurrent();
(2)Shell
每一个窗口都有一个Shell对象。Shell对象代表了与用户交互的窗口框架,并处理与窗口关联的诸如移动、改变大小等常见行为。Shell对象的获得方法:
Display display=Display.getCurrent();
Shell shell = new Shell(display);
或者:Shell shell=Display.getCurrent().getActiveShell();
(3)Workbench
Workbench是工作台,通俗地说就是代表用户界面的UI元素。工作台上有各种窗口、图标、按钮和控件,用户可以在工作台上做各种操作。获得工作台对象的方法:
IWorkbench wb=PlatformUI.getWorkbench();
工作台对象有两个方法也许很有用:
l wb.restart(),关闭应用程序并立即重新启动。
l wb.close(),正常关闭应用程序,等同于ActionFactory.QUIT_ACTION。
(4)Advisor
Advisor是建议者,用户主界面宽度、高度、图标、菜单、工具栏、颜色、操作等等配置方案需要Advisor来提出“建议”。Eclipse提供了3种类型的Advisor:
l WorkbenchAdvisor。应用程序级别,Eclipse3.0开始引入的全新类。每一个应用程序只有一个Workbench,WorkbenchAdvisor负责该工作台生命周期的管理,例如启动、关闭工作。WorkbenchAdvisor也负责该Workbench的异常处理,并负责向Workbench提供一些重要参数,例如可以指定该Workbench的初始透视图。
l WorkbenchWindowAdvisor。窗口级别。每一个窗口都有一个WorkbenchWindow- Advisor 实例。WorkbenchWindowAdvisor 负责具体窗口生命周期的管理,例如状态栏、工具栏、菜单、窗口标题、窗口大小和各种控件等等,也可以处理窗口的各种事件例程。
l ActionBarAdvisor。窗口级别。每一个窗口都有一个ActionBarAdvisor实例。ActionBarAdvisor负责管理窗口的菜单栏、状态栏、工具栏的外观和行为。
(5)View和Editor
在Eclipse RCP应用程序中,用户主要通过视图(View)和编辑器(Editor)来与程序交互。视图是可以浮动的工作窗口,负责显示数据在某个层面的状态信息。编辑器也是一种工作窗口,提供对数据进行各种操作的交互能力。至于是使用视图还是使用编辑器,没有很严格的区分,取决于开发者和用户需求的考虑,例如,应用程序的界面可以毫无障碍地全部使用视图来实现。经费测算系统只有公共参数设置功能模块使用编辑器实现,其他大部分界面均采用视图来实现。
视图扩展自ViewPart抽象类。开发者通常需要在createPartControl()方法中编写代码,以便构建视图的界面元素。下面是一个没有任何处理代码的简单视图。
package cn.edu.jfcs.ui;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
public class TeachUnitName extends ViewPart {
public TeachUnitName() {
// TODO Auto-generated constructor stub
}
public void createPartControl(Composite parent) {
// TODO Auto-generated method stub
}
public void setFocus() {
// TODO Auto-generated method stub
}
}
(6)Perspective
Perspective与视图、编辑器之间的关系类似于书包和书、笔的关系。书包里面可以放各种书和笔,书包是Perspective,而书和笔则类似于视图和编辑器。Perspective被称之为透视图,RCP应用程序是通过透视图对窗口内容进行安排和布局的,应用程序都有一个默认的透视图,每个工作台窗口则可以包含一个或多个透视图,同时用户可向透视图中添加其他UI界面元素。默认透视图被设置为固定的,不能移动,而且没有标题栏。例如运行经费测算系统后,单击【Help】→【Welcome】,将在默认透视图中打开Welcome欢迎界面。关闭该欢迎界面,就会显示一个没有标题栏、只有最小化最大化按钮的空界面,该界面即为默认的透视图。
透视图需要实现IPerspectiveFactory接口。IPerspectiveFactory可以说是产生初始页面布局和可视性透视图的工厂。在Eclipse中,工作台打开的任何新页面都需要一个透视图定义其初始布局。具体说来,就是需要向透视图工厂传递一个IPageLayout对象,通过该对象安排视图或者编辑器的初始布局。默认情况下,初始布局包含了一个可视的编辑区。当然,该编辑区也可以关闭。
2.类文件分析
(1)Application.java
对于普通Java应用程序来说,总是有一个main()方法,应用程序总是从main()开始运行。Application类似于Java应用程序的main(),即RCP应用程序运行开始于Application,Application是RCP应用程序的入口。Application实现了IPlatformRunnable接口,在RCP启动的时候将会执行该接口的run()方法。从plugin.xml可以获知,Application实际上是Eclipse org.eclipse.core.runtime.applications运行时扩展点的一个入口。Application主要代码如下:
cn.edu.jfcs.app/Application.java
import …
public class Application implements IPlatformRunnable {
public Object run(Object args) throws Exception {
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART) {
return IPlatformRunnable.EXIT_RESTART;
}
return IPlatformRunnable.EXIT_OK;
} finally {
display.dispose();
}
}
}
可以把Application当作RCP应用程序的控制者,它负责应用程序的启动、停止。Application首先创建一个Display对象,然后调用PlatformUI.createAndRunWorkbench()方法启动工作台,这将打开应用程序主窗口,并处于持续打开状态。应用程序开始处理用户的鼠标单击、鼠标移动、按键等各种事件,一直到用户关闭程序退出,这就是所谓的事件循环。当然,在关闭之前,必须销毁Display对象以释放资源(display.dispose())。
从上面的分析可以得到这样一个信息:应用程序主窗口只有在语句“int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());”调用之后才会打开并可视化。开发人员可以利用这一点做做文章,例如在其前面加入启动登录窗口、启动Derby数据库服务器、初始化处理等等工作,代码类似于下面的形式。
……
//启动Derby数据库服务器
//打开登录界面
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART) {
return IPlatformRunnable.EXIT_RESTART;
}
……
第6章中的实现用户登录处理,就是基于这种处理思路。注意到PlatformUI.createAndRun- Workbench()方法中,除了display对象,还向其传递了另外一个对象:new Application- WorkbenchAdvisor(),那么ApplicationWorkbenchAdvisor又是做什么的?
(2)ApplicationWorkbenchAdvisor.java
ApplicationWorkbenchAdvisor类负责应用程序生命周期管理,继承自WorkbenchAdvisor类。开发人员可以在该类中实现程序启动或者关闭时的某种处理。该类的具体实现只是给用户一个初始的视图界面而已,还需要配合WorkbenchWindowAdvisor、ActionBarAdvisor才能构成一个较为完整的用户界面。ApplicationWorkbenchAdvisor类主要有5个重要的方法,按照执行的先后顺序排列如表5-1所示。
表5-1 ApplicationWorkbenchAdvisor主要方法
方 法 名
|
方 法 说 明
|
initialize
|
最先调用。在窗口打开之前调用,可以用来处理初始化配置工作
|
preStartup
|
initialize之后、第一个窗口打开之前调用,可以用来处理临时或者可选处理工作
|
postStartup
|
第一个窗口打开之后但启动事件循环之前调用,可以用来进行那些需要自动处理的工作,例如弹出一个提示窗口
|
preShutdown
|
事件循环结束之后但窗口关闭之前调用,可以用来进行保存数据、关闭数据库服务器等处理工作
|
postShutdown
|
窗口关闭之后调用,可以用来进行保存应用程序状态、清除initialize创建的对象等处理工作
|
ApplicationWorkbenchAdvisor.java主要代码如下。
cn.edu.jfcs.app/ ApplicationWorkbenchAdvisor.java
import …
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor {
private static final String PERSPECTIVE_ID = "cn.edu.jfcs.perspective";
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
return new ApplicationWorkbenchWindowAdvisor(configurer);
}
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);
configurer.setSaveAndRestore(true);
}
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}
}
上述程序主要做了两件事情:一是初始化需要在主界面显示的透视图(Perspective),创建并返回ApplicationWorkbenchWindowAdvisor对象。二是初始化方法中代码configurer.setSaveAndRestore(true)用于设置应用程序每次退出时保存当前窗口状态,并在下次启动时应用,这对应用程序性能稍有影响,建议修改为false不保存。getInitialWindowPerspectiveId()方法打开默认的透视图cn.edu.jfcs.perspective。
|
如果在初始化initialize事件中编写大量处理代码,会引起应用程序启动时主窗口的延迟显示,给用户以系统速度较慢的感觉。因此,应该尽量避免。
|
(3)ApplicationWorkbenchWindowAdvisor.java
ApplicationWorkbenchWindowAdvisor类负责应用程序窗口生命周期的管理,该类扩展自WorkbenchWindowAdvisor。每一个应用程序都需要一个WorkbenchWindowAdvisor来控制窗口界面的UI元素。开发人员可以控制窗口创建时的大小、标题、位置等等,也可以添加创建、打开、还原或关闭工作台窗口时调用的方法。ApplicationWorkbenchWindowAdvisor主要方法如表5-2所示。
表5-2 ApplicationWorkbenchWindowAdvisor主要方法
方 法 名
|
方 法 说 明
|
preWindowOpen
|
窗口控件创建之前调用,可以在该方法中设置窗口的初始大小、状态栏、工具栏等的可视性
|
postWindowRestore
|
当窗口根据上一次的保存状态恢复创建之后调用,可以用来调整调整窗口恢复状态
|
postWindowCreate
|
窗口创建之后调用,可以用于调整窗口
|
postWindowOpen
|
窗口已经打开之后调用,可以用来注册窗口监听,例如在此方法中实现系统托盘
|
下面我们来看看Eclipse自动生成的ApplicationWorkbenchWindowAdvisor.java主要代码如下:
cn.edu.jfcs.app/ ApplicationWorkbenchWindowAdvisor.java
import …
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
super(configurer);
}
public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(700, 550)); //定义窗口初始化大小
configurer.setShowCoolBar(false); //不显示工具栏
configurer.setShowStatusLine(false); //不显示状态栏
configurer.setTitle("jfcs"); //窗口标题为jfcs
}
}
该类创建了一个ApplicationActionBarAdvisor对象,并通过preWindowOpen()方法方法配置窗口。在preWindowOpen()方法中,首先生成了configurer对象,通过该对象配置窗口的大小、工具栏、状态栏、标题等可视化元素,也就是说控制窗口的外观。默认状态下工具栏和状态栏都是隐藏的。IWorkbenchWindowConfigurer是一个接口类,该接口类提供了很多set/get方法以便用户访问存取工作台窗口的配置。实际上,大家可能也注意到了,每种类型的Advisor都有一个对应的configurer。ApplicationWorkbenchAdvisor中的IWorkbenchConfigurer、ApplicationWorkbenchWindowAdvisor中的IWorkbenchWindowConfigurer、后面Application- ActionBarAdvisor中的IActionBarConfigurer,configurer是与工作台、窗口、菜单、工具栏和状态栏打交道的一座方便的桥梁。
(4)ApplicationActionBarAdvisor.java
ApplicationActionBarAdvisor.java类负责定义窗口的行为,该类扩展自ActionBarAdvisor。具体地说,该类用于构建菜单栏、工具栏和状态行。ActionBarAdvisor自然是负责菜单栏、工具栏和状态行的创建和注册。ApplicationActionBarAdvisor主要方法如表5-3所示。
表5-3 ApplicationActionBarAdvisor主要方法
方 法 名
|
方 法 说 明
|
void makeActions(IWorkbenchWindow window)
|
注册菜单或者工具栏的动作
|
void fillMenuBar(IMenuManager menuBar)
|
添加菜单栏
|
void fillCoolBar(ICoolBarManager coolBar)
|
添加工具栏
|
void fillStatusLine(IStatusLineManager statusLine)
|
添加状态栏
|
ApplicationActionBarAdvisor.java主要代码如下。
cn.edu.jfcs.app/ ApplicationActionBarAdvisor.java
import …
public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
private IWorkbenchAction introAction;
public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
super(configurer);
}
protected void makeActions(IWorkbenchWindow window) {
//利用ActionFactory动作工厂创建introAction
introAction = ActionFactory.INTRO.create(window);
register(introAction);
}
protected void fillMenuBar(IMenuManager menuBar) {
MenuManager helpMenu = new MenuManager("&Help",
IWorkbenchActionConstants.M_HELP);
menuBar.add(helpMenu);
helpMenu.add(introAction);
}
}
该程序创建了一个帮助菜单栏,其子菜单所执行的动作采用Eclipse内置的ActionFactory.INTRO,执行该动作将显示Welcome欢迎画面。
(5)Perspective.java
Perspective类主要负责界面布局的安排。Perspective.java代码如下。
cn.edu.jfcs.app/ Perspective.java
import …
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea(); //获得布局的编辑区
layout.setEditorAreaVisible(false); //隐藏编辑区
layout.setFixed(true); //固定布局
// 此处加入各种视图
}
}
createInitialLayout()方法通常用于创建初始的界面布局,当前是空实现,所以打开经费测算系统并关闭欢迎画面后,界面会出现空白,后面将加入主界面视图。
5.1.4 定制应用程序窗口属性
向导生成的应用程序主界面并不能满足要求,存在很多问题,例如,主界面运行时没有自动居中,主界面大小没有固定,主窗口标题栏文字应该是“高校经费测算系统”。再看看图5-3、图5-4的标题栏有区别没有?当然有,图5-3所示界面的标题栏是很漂亮的弧线形,而图5-4所示界面的标题栏则不是。如此等等,需要重新设置。
1.闪屏画面
应用程序主界面显示之前往往需要做一些初始化处理工作,就是启动时间可能稍微长一些,如果没有任何提示,用户可能会感到困惑,闪屏画面能够较好地解决这个问题。准备一幅24bit色BMP格式的图片,注意图片大小不要超过500mm×300mm。将该图片复制到项目文件夹中替换掉原来的splash.bmp文件即可。
2.不保存窗口状态
将ApplicationWorkbenchAdvisor.java的initialize()方法中的语句:configurer.setSaveAndRestore(true);
修改为:configurer.setSaveAndRestore(false);
前文说过,设置为true,应用程序每次退出时将保存窗口状态,此处并不需要且对性能有轻微影响,所以设置为false。
3.定制窗口式样
再来定制主窗口。前面已经介绍过,在ApplicationWorkbenchWindowAdvisor.java的preWindowOpen()方法中定制窗口式样,现在修改如下。
cn.edu.jfcs.app/ ApplicationWorkbenchWindowAdvisor.java
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
//窗口设定为800x600
configurer.setInitialSize(new Point(800, 600));
//暂时不显示工具栏
configurer.setShowCoolBar(false);
//显示状态栏
configurer.setShowStatusLine(true);
//窗口只显示最小化、关闭按钮
configurer.setShellStyle(SWT.MIN | SWT.CLOSE);
//设置窗口标题
configurer.setTitle("高校经费测算系统");
}
执行上步操作后,我们会发现configurer.setShellStyle(SWT.MIN | SWT.CLOSE)这句代码的旁边出现一个带红色叉叉的小灯泡,这意味着该行代码有问题,这是因为使用了SWT.MIN常量而又没有导入相应类。解决方法很简单,只需鼠标单击小灯泡,根据弹出的提示导入包import org.eclipse.swt.SWT即可,这也是Eclipse很贴心的小功能。现在运行看看,程序主界面已经有了较大变化。
程序中最后一句代码中的“高校经费测算系统”是一个自定义常量。一个系统中有很多类似的自定义常量,例如图片的名称、视图的名称等等,而这些常量可能不止一个地方需要使用到。一个很好的方法是创建一个接口文件,将全部常量的定义放置到该接口文件中,这样可以统一管理,而且维护方便。如果要修改某个常量的值,只需要到接口文件中修改就可以了。下面来实现该处理,新建一个包cn.edu.jfcs.sys,在该包下新建接口类IAppConstants.java,代码类似于以下形式。
package cn.edu.jfcs.sys;
public interface IAppConstants {
public static final String APPLICATION_TITLE="高校经费测算系统";
}
现在只需要将ApplicationWorkbenchWindowAdvisor.java中preWindowOpen()方法的configurer.setTitle("高校经费测算系统")修改为configurer.setTitle(IAppConstants.APPLICATION_ TITLE)即可。记得导入cn.edu.jfcs.sys.IAppConstants类。
|
以后还会不断往该接口文件中添加常量定义。为了避免不必要的麻烦,建议读者在实际操作时先将本书附带源代码的IAppConstants.java类直接复制到自己的项目中。
|
4.窗口自动居中
窗口居中需要手工编程实现,编写之前先得想想代码放在哪儿?还是放在preWindowOpen()方法中吗?当然不行,preWindowOpen()是配置窗口的构成元素,即形成窗口本身的构成部件,而居中则是定义窗口的位置,显然不属于窗口构成元素。postWindowOpen()可以胜任此项工作,因为postWindowOpen()主要用来处理那些需要一个现成窗口才能进行的事件处理。
在代码编辑视图中单击鼠标右键,在弹出的快捷菜单中选择【Source】→【Override/ Implement Methods…】命令,弹出“Override/Implement Methods”对话框,勾选postWindowOpen()方法,默认将在光标所在处插入postWindowOpen()方法。这又是Eclipse的一个很贴心的功能,希望读者熟练使用。改写该方法的代码如下:
cn.edu.jfcs.app/ ApplicationWorkbenchWindowAdvisor.java
public void postWindowOpen() {
//设置窗口自动居中
Shell shell = getWindowConfigurer().getWindow().getShell();
Rectangle screenSize = Display.getDefault().getClientArea();
Rectangle frameSize = shell.getBounds();
shell.setLocation((screenSize.width - frameSize.width) / 2,(
screenSize.height - frameSize.height) / 2);
}
该方法通过默认Display对象来设置屏幕宽度和高度,通过Shell对象获得当前窗口的宽度和高度,两者分别相减后再除以2,计算得到窗口左上角的(x,y)坐标。不要忘了导入相关的类,再看看运行后窗口是否自动居中。
5.设置视图标题栏的弧线形外观
大家肯定都喜欢图5-3所示界面中弧线形的标题栏,这种风格的标题栏涉及到工作台UI属性(org.eclipse.ui Preference):SHOW_TRADITIONAL_STYLE_TABS。可以通过三种方法进行设置。
(1)硬编码实现
硬编码实现是指通过直接编写代码实现。打开ApplicationWorkbenchAdvisor.java文件,修改initialize()方法代码如下:
cn.edu.jfcs.app/ ApplicationWorkbenchAdvisor.java
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);
configurer.setSaveAndRestore(false);
PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.
SHOW_TRADITIONAL_STYLE_TABS, false);
}
相关的属性很多,具体可以查看IWorkbenchPreferenceConstants接口文件。方法是,按住【Ctrl】键,将鼠标移动到IWorkbenchPreferenceConstants上面,IWorkbenchPreferenceConstants下面会出现下划线,单击鼠标左键即可。对于Eclipse的其他方法也是如此操作。这里先简单介绍几个常用属性。
表5-4 IWorkbenchPreferenceConstants常见属性
属 性 名
|
属 性 说 明
|
EDITOR_MINIMUM_CHARACTERS
|
但很多编辑器重叠时,设置编辑器标题文字的最短长度。默认为8个字符
|
SHOW_PROGRESS_ON_STARTUP
|
设置启动时是否显示进度条。默认值false
|
DOCK_PERSPECTIVE_BAR
|
设置透视图标题栏停泊位置。默认值为TOP_RIGHT,还可以设置为TOP_LEFT、LEFT
|
SHOW_TEXT_ON_PERSPECTIVE_BAR
|
设置透视图是否显示标题文本。默认值为true
|
SHOW_INTRO
|
启动时是否显示欢迎画面。默认值为true
|
|
可能有些人喜欢每次启动时显示欢迎画面,则可以在initialize()方法中加入:
PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.SHOW_INTRO, true);
|
(2)修改产品默认配置文件
可以创建一个初始化配置文件,使用默认的配置文件名plugin_customization.ini。在项目名称上单击鼠标右键,选择【New】→【File】,在File name后输入plugin_customization.ini,单击【Finish】按钮,输入以下内容。
#设置视图标题栏的弧线形外观
org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
#编辑器标题栏提示文字最短长度
org.eclipse.ui/ EDITOR_MINIMUM_CHARACTERS =12
(3)自定义配置文件
如果你不喜欢默认的配置文件,完全可以更改配置文件名(本书采用这种方法),具体步骤如下。
① 双击pludin.xml文件,再单击“Extensions”页。
② 展开org.eclipse.core.runtime.products,在jfcs(Product)上单击鼠标右键,选择【New】→【property】。
③ 在Extension Element Details下的name后的文本框中输入属性名preferenceCustomization
(属性名不能更改),value后的文本框中输入AppPref.ini(可任意命名),具体如图5-10所示。若要查看org.eclipse.core.runtime.products有哪些可供配置的属性,则只需要单击org.eclipse.core.runtime.products名,然后再单击右边的Open extension point description,Eclipse将打开关于Products扩展点的属性描述,如图5-11所示。注意到该属性默认的文件正是前面所说的plugin_customization.ini。
图5-10 添加属性设置视图
图5-11 org.eclipse.core.runtime.products扩展点描述
④ 在项目名称上单击鼠标右键,选择【New】→【File】,在File name后输入AppPref.ini,单击【Finish】按钮,输入配置内容即可。
这里提醒一下,如果做了很多设置,而运行时似乎没有生效,这是由于Eclipse缓存了旧配置信息。解决方法:选择系统菜单的【Run】→【Run…】,弹出“Run”对话框,先单击“Eclipse Application”,再单击“jfcs”,勾选“Clean workspace data before launching”,不要勾选“Ask for confirmation before cleaning”。这样可以保证每次运行都是最新结果,设置画面如图5-12所示。
图5-12 运行设置对话框
|
SHOW_INTRO比较特别。如果使用ini配置文件的方式,无论使用默认配置文件还是自定义配置文件,产品打包发布后(不在Eclipse环境中运行)只是首次启动时出现欢迎画面,这是因为Eclipse在运行结束时会修改工作空间目录中org.eclipse.ui.prefs文件的showIntro=false,所以下次启动时将不会出现欢迎画面。如果希望程序每次启动时都出现欢迎画面,需要采取硬编码的方式!
|