在使用Eclipse RCP進行桌面程序開發(一):快速起步中,我們通過Eclipse的插件開發 向導,逐步建立了一個RCP應用程序,但是,這個程序沒有任何功能,難以激起我們學習的興 趣。在這一節,我們將一起探索怎樣在程序中添加菜單和工具條。先看一下成果:
圖一、圖二:帶有菜單和工具條的RCP程序
圖三:工具欄上的按鈕的提示文本
圖四:點擊菜單項或者工具欄按鈕後,彈出一個簡單的對話框。
這裡需要說明一點,為什麼要在講菜單和工具欄的時候一起講對話框,這是因為對話框是 我們所能想到的最簡單最直接的用戶交互方式,在對話框上可以添加各種各樣的控件來實現 復雜的功能,為了讓我們點擊菜單項的時候能夠看到效果,這裡就用了一個簡單的對話框。 當然,當我們以後接觸到視圖、編輯器和透視圖這樣的概念之後,我們能使用的用戶交互方 式就不僅僅只是對話框了。
打開我們上一節使用向導建立的工程,可以發現工程下面自動生成了如下文件:
Application.java
ApplicationWorkbenchAdvisor.java
ApplicationWorkbenchWindowAdvisor.java
ApplicationActionBarAdvisor.java
Perspective.java
plugin.xml
這裡的Application.java是我們整個程序的入口點,我們的程序運行的時候,會先執行 Application的run方法,run方法的代碼如下:
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類的實例。其代碼如下:
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的透視圖和視圖。