在使用Eclipse RCP进行桌面程序开发(一):快速起步中,我们通过Eclipse的插件开发向导,逐步建立了一个RCP应用程序,但是,这个程序没有任何功能,难以激起我们学习的兴趣。在这一节,我们将一起探索怎样在程序中添加菜单和工具条。先看一下成果:
图一、图二:带有菜单和工具条的RCP程序


图三:工具栏上的按钮的提示文本

图四:点击菜单项或者工具栏按钮后,弹出一个简单的对话框。

这里需要说明一点,为什么要在讲菜单和工具栏的时候一起讲对话框,这是因为对话框是我们所能想到的最简单最直接的用户交互方式,在对话框上可以 添加各种各样的控件来实现复杂的功能,为了让我们点击菜单项的时候能够看到效果,这里就用了一个简单的对话框。当然,当我们以后接触到视图、编辑器和透视 图这样的概念之后,我们能使用的用户交互方式就不仅仅只是对话框了。
打开我们上一节使用向导建立的工程,可以发现工程下面自动生成了如下文件:
Application.java
ApplicationWorkbenchAdvisor.java
ApplicationWorkbenchWindowAdvisor.java
ApplicationActionBarAdvisor.java
Perspective.java
plugin.xml
这里的Application.java是我们整个程序的入口点,我们的程序运行的时候,会先执行Application的run方法,run方法的代码如下:
1
public Object run(Object args) throws Exception
{
2
Display display
=
PlatformUI.createDisplay();
3
try
{
4
int
returnCode
=
PlatformUI.createAndRunWorkbench(display,
new
ApplicationWorkbenchAdvisor());
5
if
(returnCode
==
PlatformUI.RETURN_RESTART)
{
6
return
IPlatformRunnable.EXIT_RESTART;
7
}
8
return
IPlatformRunnable.EXIT_OK;
9
}
finally
{
10
display.dispose();
11
}
12
}
在第4行我们可以看出,该入口函数将创建用户界面的工作交给了ApplicationWorkbenchAdvisor类。接着,我们打开ApplicationWorkbenchAdvisor.java,代码如下:
1
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor
{
2
3
private
static
final
String PERSPECTIVE_ID
=
"
cn.blogjava.youxia.rcp_start.perspective
"
;
4
5
public
WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
{
6
return
new
ApplicationWorkbenchWindowAdvisor(configurer);
7
}
8
9
public
String getInitialWindowPerspectiveId()
{
10
return
PERSPECTIVE_ID;
11
}
12
}
可以看出,这个类的工作就是为我们的程序指定默认的透视图,然后把创建窗口的工作交给了 ApplicationWorkbenchWindowAdvisor类。接着,我们打开 ApplicationWorkbenchWindowAdvisor.java文件,看到代码如下:
1
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
{
2
3
public
ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
{
4
super
(configurer);
5
}
6
7
public
ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer)
{
8
return
new
ApplicationActionBarAdvisor(configurer);
9
}
10
11
public
void
preWindowOpen()
{
12
IWorkbenchWindowConfigurer configurer
=
getWindowConfigurer();
13
configurer.setInitialSize(
new
Point(
600
,
450
));
14
configurer.setShowCoolBar(
true
);
15
configurer.setShowStatusLine(
false
);
16
configurer.setTitle(
"
第一个RCP程序
"
);
17
18
}
19
20
}
这个类的功能很强大,我们可以重载它的preWindowCreate、postWindowCreate、preWindowOpen、 postWindowOpen等方法,以便修改我们窗口的外观。在这里可以看出,我们重载了preWindowOpen方法来设置窗口的大小和让工具栏可 见。很显然,这个类的另外一个功能,就是把创建菜单和工具栏的任务交给了ApplicationActionBarAdvisor类。
到这里,谜底已经揭晓,要创建我们自己的菜单和工具条,就一定是在ApplicationActionBarAdvisor.java中做文章了。不错,打开这个文件,我们可以看到这个类有两个重要的方法:
protected void makeActions(IWorkbenchWindow window);
protected void fillMenuBar(IMenuManager menuBar);
我 们可以在makeActions方法中创建我们的Action,什么是Action呢?Action是jface中的一个概念,在jface中通过 org.eclipse.jface.action中的Action和ActionContributionItem类实现了视图和处理代码的分离,这样 无论何时用户触发了一个控件的事件,都会激活一个相应的Action类实例来进行时间处理。毫无疑问,我们的菜单项是一个Action类的子类了。
下面请看ApplicationActionBarAdvisor.java的源代码:
1
package cn.blogjava.youxia.rcp_start;
2
3
import org.eclipse.jface.action.IMenuManager;
4
import org.eclipse.jface.action.MenuManager;
5
import org.eclipse.ui.IWorkbenchWindow;
6
import org.eclipse.ui.application.ActionBarAdvisor;
7
import org.eclipse.ui.application.IActionBarConfigurer;
8
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
9
import cn.blogjava.youxia.actions.Action1;
10
11
public class ApplicationActionBarAdvisor extends ActionBarAdvisor
{
12
13
private
IWorkbenchAction action1;
14
15
public
ApplicationActionBarAdvisor(IActionBarConfigurer configurer)
{
16
super
(configurer);
17
}
18
19
protected
void
makeActions(IWorkbenchWindow window)
{
20
action1
=
new
Action1(window);
21
action1.setText(
"
第一个菜单项
"
);
22
action1.setId(
"
cn.blogjava.youxia.actions.action1
"
);
23
register(action1);
24
}
25
26
protected
void
fillMenuBar(IMenuManager menuBar)
{
27
MenuManager newMenu
=
new
MenuManager(
"
第一个菜单
"
,
"
cn.blogjava.youxia.firstmenu
"
);
28
menuBar.add(newMenu);
29
newMenu.add(action1);
30
}
31
32
}
可以看出,我们通过创建cn.blogjava.youxia.actions.Action1类的实例来创建一个菜单项,然后把它加入到菜单 newMenu中,然后再把newMenu加入menuBar中,整个过程很容易理解。那么register(action1)是做什么的呢?这是为了把 我们的Action的实例注册到工作台中,这样当我们的工作台销毁的时候,我们的Action也可以被销毁。
下面请看Action1类的源代码:
1
package cn.blogjava.youxia.actions;
2
3
import org.eclipse.jface.action.Action;
4
import org.eclipse.ui.IWorkbenchWindow;
5
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
6
import cn.blogjava.youxia.rcp_start.FirstDialog;
7
8
9
public class Action1 extends Action implements IWorkbenchAction
{
10
11
private
IWorkbenchWindow workbenchWindow;
12
13
public
Action1(IWorkbenchWindow window)
{
14
if
(window
==
null
)
{
15
throw
new
IllegalArgumentException();
16
}
17
18
this
.workbenchWindow
=
window;
19
}
20
21
public
void
run()
{
22
//
make sure action is not disposed
23
if
(workbenchWindow
!=
null
)
{
24
//
在这里添加功能
25
FirstDialog dg
=
new
FirstDialog(workbenchWindow.getShell());
26
dg.open();
27
28
}
29
}
30
31
public
void
dispose()
{
32
workbenchWindow
=
null
;
33
34
}
35
36
}
在构造函数中保存我们工作台窗口的引用,在run方法中执行功能,是不是很简单?在这里,我们用到了一个对话框类 cn.blogjava.youxia.rcp_start.FirstDialog,这个类从 org.eclipse.swt.widgets.Dialog类继承,熟悉swt的朋友一定不会陌生。我建议大家可以使用Designer插件,这个插 件对swt/jface提供非常好的可视化支持,在这个对话框中,我们只简单的添加了两个按钮。
FirstDialog.java源文件如下:
1
package cn.blogjava.youxia.rcp_start;
2
3
import org.eclipse.swt.SWT;
4
import org.eclipse.swt.events.SelectionAdapter;
5
import org.eclipse.swt.events.SelectionEvent;
6
import org.eclipse.swt.widgets.Button;
7
import org.eclipse.swt.widgets.Dialog;
8
import org.eclipse.swt.widgets.Display;
9
import org.eclipse.swt.widgets.Shell;
10
11
12
public class FirstDialog extends Dialog
{
13
14
protected
Shell shell;
15
16
private
int
result;
17
18
public
FirstDialog(Shell parent,
int
style)
{
19
super
(parent, style);
20
}
21
22
public
FirstDialog(Shell parent)
{
23
this
(parent, SWT.NONE);
24
}
25
26
public
int
open()
{
27
createContents();
28
shell.open();
29
shell.layout();
30
Display display
=
getParent().getDisplay();
31
while
(
!
shell.isDisposed())
{
32
if
(
!
display.readAndDispatch())
33
display.sleep();
34
}
35
return
result;
36
}
37
38
protected
void
createContents()
{
39
shell
=
new
Shell(getParent(), SWT.DIALOG_TRIM
|
SWT.APPLICATION_MODAL);
40
shell.setSize(
150
,
70
);
41
shell.setText(
"
第一个对话框
"
);
42
43
final
Button okButton
=
new
Button(shell, SWT.NONE);
44
okButton.addSelectionListener(
new
SelectionAdapter()
{
45
public
void
widgetSelected(SelectionEvent e)
{
46
result
=
1
;
47
shell.dispose();
48
}
49
}
);
50
okButton.setText(
"
OK
"
);
51
okButton.setBounds(
10
,
10
,
48
,
22
);
52
53
final
Button cancelButton
=
new
Button(shell, SWT.NONE);
54
cancelButton.addSelectionListener(
new
SelectionAdapter()
{
55
public
void
widgetSelected(SelectionEvent e)
{
56
result
=
2
;
57
shell.dispose();
58
}
59
}
);
60
cancelButton.setText(
"
Cancel
"
);
61
cancelButton.setBounds(
89
,
10
,
48
,
22
);
62
}
63
64
}
65
上面所讲的,只是添加菜单和工具栏的第一种方法,这种方法把构建菜单的工作以静态代码的方式加入到了ApplicationActionBarAdvisor类中,如果需要修改用户界面,则需要修改代码并重新编译。
添加菜单项的第二种方法就要简单得多,而且修改起来也方便,还可以对菜单项实现更加灵活的控制,但是,需要对Eclipse的插件基础有比较好的了解。那这第二种方法就是通过扩展actionSets扩展点来添加菜单。
对扩展点的扩展,可以通过编辑plugin.xml文件了实现,比如我们添加的第二个菜单项,其配置文件如下:
1
< extension
2
id ="cn.blogjava.youxia.actionset"
3
name ="我的菜单扩展"
4
point ="org.eclipse.ui.actionSets" >
5
< actionSet
6
description ="第一个扩展"
7
id ="RCP_Start.actionSet1"
8
label ="RCP_Start.actionSet1"
9
visible ="true" >
10
< action
11
class ="cn.blogjava.youxia.actions.Action2"
12
icon ="icons/alt_window_16.gif"
13
id ="RCP_Start.action2"
14
label ="第二个菜单项"
15
menubarPath ="cn.blogjava.youxia.firstmenu/additions"
16
style ="push"
17
toolbarPath ="additions"
18
tooltip ="第二个菜单项的按钮" />
19
</ actionSet >
20
</ extension >
其实Eclipse为我们提供了很好的可视化plugin.xml的编辑器,如下图,我们可以对菜单的外观进行和行为进行灵活的控制:

从配置文件中我们可以看到,我们为这第二个菜单项指定的Action是cn.blogjava.youxia.actions.Action2 类,这个类我们必须实现org.eclipse.ui.IWorkbenchWindowActionDelegate接口,这个接口中比 org.eclipse.jface.actions.Action中多定义了一个方法public void selectionChanged(IAction action, ISelection selection),这个方法是必须的,以便工作台窗口在用户选定哪一项资源的时候通知我们的Action类的实例。其代码如下:
1
package cn.blogjava.youxia.actions;
2
3
import org.eclipse.jface.action.IAction;
4
import org.eclipse.jface.viewers.ISelection;
5
import org.eclipse.ui.IWorkbenchWindow;
6
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
7
import cn.blogjava.youxia.rcp_start.FirstDialog;
8
9
public class Action2 implements IWorkbenchWindowActionDelegate
{
10
11
private
IWorkbenchWindow window;
12
13
public
void
dispose()
{
14
//
TODO
15
16
}
17
18
public
void
init(IWorkbenchWindow window)
{
19
//
TODO
20
this
.window
=
window;
21
22
}
23
24
public
void
run(IAction action)
{
25
//
TODO
26
FirstDialog dg
=
new
FirstDialog(window.getShell());
27
dg.open();
28
29
}
30
31
public
void
selectionChanged(IAction action, ISelection selection)
{
32
//
TODO
33
34
}
35
36
}
总结:通过向工作台中添加菜单和工具栏,并使用对话框作为与用户交互的基础,我们已经基本上可以构建功能比较复杂的程序了。但这仅仅只是RCP编程的开端。下一节,我们将一起探索Eclipse的透视图和视图。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2010-12-19 在source insight中加入TortoiseSVN的功能