使用Eclipse RCP進行桌面程序開發(三):視圖和透視圖
Posted on 2006-11-24 22:02 京山游俠 閱讀(33511) 評論(40) 編輯 收藏 所屬分類: 擁抱Eclipse RCP
使用Eclipse RCP進行桌面程序開發(一):快速起步
使用Eclipse RCP進行桌面程序開發(二):菜單、工具欄和對話框
Eclipse RCP開發中,和用戶進行交互最多的界面,應該是視圖了,而透視圖就是將已有的視圖、菜單、工具欄、編輯器等等進行組合和布局。看完這一節,我們就可以建立如下圖這樣的程序界面了。

首先我們來介紹一下視圖,建立一個視圖其實非常簡單,只要從org.eclipse.ui.part.ViewPart繼承一個類,然后在plugin.xml中進行視圖的配置。其中,向視圖中添加控件的操作,我們即可以手工編寫,也可以使用Designer插件,我這里推薦大家使用Designer插件,該插件對RCP提供功能非常強大的支持,如果使用Designer插件開發視圖,則plugin.xml文件也不需要我們手動修改了。
比如我們上圖中的第一個視圖,就是從ViewPart繼承一個類,然后在上面加入了幾個swt的控件,做得非常得簡單,而它的配置文件如下:
可以看到,實現這個視圖的class為cn.blogjava.youxia.views.FirstView,那么我們看看FirstView.java吧:
可見,我們為我們的產品添加了一個prefereneCustomization屬性,該屬性的值為plugin_customization.ini文件,在該文件中,我們可以配置我們的樣式。在這里,它的內容如下:
事實上,在這個文件中可以定義的參數有上百個,大家可以查看Eclipse的文檔。
這個時候,效果應該是這樣的了:

好了,我們現在對以上的代碼做一個總結。我不是寫教科書,在Blog中也沒有寫得那么詳細的條件。我們這里主要關注在哪個地方對代碼進行擴展,可以達到我們想要的效果。比如,我們要創建視圖,就是需要擴展org.eclipse.ui.part.ViewPart類,然后向其中添加控件,再然后配置plugin.xml文件,最后修改透視圖的代碼,以便它能夠顯示出來。
在ViewPart類中,我們添加控件的操作主要是在public void createPartControl(Composite parent)這個方法中進行,而方法最后會調用以下三個方法:
createActions();
initializeToolBar();
initializeMenu();
從這三個方法的方法名我們不難看出,它們的功能是創建視圖特有的菜單欄和工具欄的,結合上一小節的內容,我們應該很快就可以探索到怎么給視圖添加漂亮的工具欄了,這里我不再羅嗦。
再來看Perspective.java,不難發現,所有的透視圖類都需要實現IPerspectiveFactory接口,而該接口的createInitialLayout方法,就是描述工作臺窗口中編輯器和視圖的布局。默認情況下,透視圖中只包含一個編輯器區域,就是我們第一節中看到的那個效果。在createInitialLayou中,我們可以通過以下幾個方法向透視圖中添加視圖、編輯器和菜單:
addView?? —— 添加視圖
addActionSet —— 添加菜單和工具欄
createFolder —— 創建一個IForderLayou,可以讓多個視圖重疊在同一個位置
寫到這里,肯定有人會問,如果我要創建一個象Eclipse中的資源視圖這樣的視圖,該怎么做呢?這我們就要感謝org.eclipse.jface.viewers包了,Viewer,這里翻譯為查看器,它和視圖是不一樣的。JFace查看器是Jface對SWT部件的封裝,它簡化了我們對小部件的操作。在使用查看器的時候,它的數據使用單獨的模型對象來保存,使用查看器的setInput方法可以為查看器設置模型,此外,在使用查看器的時候,需要為它提供ContentProvider(內容提供器)和LabelProvider(標簽提供器)。
JFace查看器主要分為以下幾類:
1. ListViewer: 對應于SWT的列表控件,目的是將列表中的元素映射至SWT列表控件
2. TreeViewer: 對應于SWT的樹控件,提供樹的展開和折疊等基本操作
3. TableViewer: 對應于SWT的表控件,映射表中的元素
4. TextViewer: 對應于SWT的StyledText控件,創建編輯器的時候,使用這個查看器是最合適不過了。
好了,介紹性的文字就寫到這里,我想大家一定已經知道了探索的方向。下面,我們看一個簡單的示例,就是這篇文章開頭給出的效果圖。它是我模仿醫院管理系統做的一個簡單例子,左邊的視圖就是使用了一個ListView查看器。這里給出它的關鍵代碼:
可以看到,這里需要設置內容提供器和標簽提供器和模型。下面,我們先創建一個病人類Person.java:
下面,創建模型類PersonModel.java,在構造函數中我們向List中填入了幾個初始化數據:
在這里,我們還定義了一個Listener接口,為什么要有這么一個接口呢?就是為了讓我們模型中的數據被改變時,查看器能夠相應更改。下面,我們實現內容提供器,該內容提供器實現了PersonModel中定義的Listener接口,如下PersonContentProvider.java:
我們知道,列表中的元素都是Person類的對象,怎么讓他們顯示出來呢,需要實現標簽提供器,在標簽提供器中,我們可以設置對象顯示的圖標和文字,如下PersonLabelProvider.java:
運行程序,就得到了文章開頭的效果,但是不能在右邊的視圖中顯示病人的詳細信息。
如果要做到視圖的交互,需要添加事件的監聽器。使用Java 進行GUI開發的人應該都不會陌生,而我在RCP上,也處于探索階段,更深一步的內容,讓我們自己慢慢研究吧。
使用Eclipse RCP進行桌面程序開發(二):菜單、工具欄和對話框
Eclipse RCP開發中,和用戶進行交互最多的界面,應該是視圖了,而透視圖就是將已有的視圖、菜單、工具欄、編輯器等等進行組合和布局。看完這一節,我們就可以建立如下圖這樣的程序界面了。
首先我們來介紹一下視圖,建立一個視圖其實非常簡單,只要從org.eclipse.ui.part.ViewPart繼承一個類,然后在plugin.xml中進行視圖的配置。其中,向視圖中添加控件的操作,我們即可以手工編寫,也可以使用Designer插件,我這里推薦大家使用Designer插件,該插件對RCP提供功能非常強大的支持,如果使用Designer插件開發視圖,則plugin.xml文件也不需要我們手動修改了。
比如我們上圖中的第一個視圖,就是從ViewPart繼承一個類,然后在上面加入了幾個swt的控件,做得非常得簡單,而它的配置文件如下:
1
<extension
2
?????????point="org.eclipse.ui.views">
3
??????<view
4
????????????class="cn.blogjava.youxia.views.FirstView"
5
????????????id="cn.blogjava.youxia.views.FirstView"
6
????????????name="第一個View"/>
7
</extension>

2

3

4

5

6

7

可以看到,實現這個視圖的class為cn.blogjava.youxia.views.FirstView,那么我們看看FirstView.java吧:
?1
package?cn.blogjava.youxia.views;
?2
?3
import?org.eclipse.jface.action.IMenuManager;
?4
import?org.eclipse.jface.action.IToolBarManager;
?5
import?org.eclipse.jface.viewers.TableViewer;
?6
import?org.eclipse.swt.SWT;
?7
import?org.eclipse.swt.widgets.Composite;
?8
import?org.eclipse.swt.widgets.Label;
?9
import?org.eclipse.swt.widgets.Table;
10
import?org.eclipse.swt.widgets.Text;
11
import?org.eclipse.ui.part.ViewPart;
12
13
public?class?FirstView?extends?ViewPart?
{
14
15
????private?Table?table;
16
????private?Text?text_1;
17
????private?Text?text;
18
????public?static?final?String?ID?=?"cn.blogjava.youxia.views.FirstView";?//$NON-NLS-1$
19
20
????/**?*//**
21
?????*?Create?contents?of?the?view?part
22
?????*?@param?parent
23
?????*/
24
????@Override
25
????public?void?createPartControl(Composite?parent)?
{
26
????????Composite?container?=?new?Composite(parent,?SWT.NONE);
27
28
????????final?Label?label?=?new?Label(container,?SWT.NONE);
29
????????label.setText("姓名:");
30
????????label.setBounds(56,?41,?36,?12);
31
32
????????text?=?new?Text(container,?SWT.BORDER);
33
????????text.setBounds(98,?38,?80,?15);
34
35
????????final?Label?label_1?=?new?Label(container,?SWT.NONE);
36
????????label_1.setText("性別:");
37
????????label_1.setBounds(212,?41,?30,?12);
38
39
????????text_1?=?new?Text(container,?SWT.BORDER);
40
????????text_1.setBounds(252,?38,?80,?15);
41
42
????????final?TableViewer?tableViewer?=?new?TableViewer(container,?SWT.BORDER);
43
????????//tableViewer.setInput(new?Object());
44
????????table?=?tableViewer.getTable();
45
????????table.setBounds(56,?75,?374,?143);
46
????????table.setItemCount(10);
47
????????table.setLinesVisible(true);
48
????????//
49
????????createActions();
50
????????initializeToolBar();
51
????????initializeMenu();
52
????????????}
53
54
????/**?*//**
55
?????*?Create?the?actions
56
?????*/
57
????private?void?createActions()?
{
58
????????//?Create?the?actions
59
????}
60
61
????/**?*//**
62
?????*?Initialize?the?toolbar
63
?????*/
64
????private?void?initializeToolBar()?
{
65
????????IToolBarManager?toolbarManager?=?getViewSite().getActionBars()
66
????????????????.getToolBarManager();
67
????}
68
69
????/**?*//**
70
?????*?Initialize?the?menu
71
?????*/
72
????private?void?initializeMenu()?
{
73
????????IMenuManager?menuManager?=?getViewSite().getActionBars()
74
????????????????.getMenuManager();
75
????}
76
77
????@Override
78
????public?void?setFocus()?
{
79
????????//?Set?the?focus
80
????}
81
82
????}

?2

?3

?4

?5

?6

?7

?8

?9

10

11

12

13



14

15

16

17

18

19

20


21

22

23

24

25



26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54


55

56

57



58

59

60

61


62

63

64



65

66

67

68

69


70

71

72



73

74

75

76

77

78



79

80

81

82

其中,添加控件的代碼由Disgner插件自動生成。這個時候,如果我們運行程序的話,我們的視圖還不會被顯示出來。為了讓我們的視圖可以顯示,我們還需要修改Perspective.java文件,代碼如下:
?1
package?cn.blogjava.youxia.rcp_start;
?2
?3
import?org.eclipse.ui.IPageLayout;
?4
import?org.eclipse.ui.IPerspectiveFactory;
?5
?6
public?class?Perspective?implements?IPerspectiveFactory?{
?7
?8
????public?void?createInitialLayout(IPageLayout?layout)?{
?9
????????String?editorArea?=?layout.getEditorArea();
10
????????layout.addView("cn.blogjava.youxia.views.FirstView",?IPageLayout.RIGHT,?0.2f,?editorArea);
11
????}
12
}

?2

?3

?4

?5

?6

?7

?8

?9

10

11

12

運行程序,得到如下效果:
我們可以發現,上面這個視圖的標簽不是我們通常看到的波浪形,我們可以通過配置文件的方式來更改產品的樣式。
首先,在plugin.xml中對org.eclipse.core.runtime.products擴展點的屬性進行更改,如下:
?1
<extension
?2
?????????id="product"
?3
?????????point="org.eclipse.core.runtime.products">
?4
??????<product
?5
????????????application="cn.blogjava.youxia.rcp_start.application"
?6
????????????name="第一個RCP程序">
?7
?????????<property
?8
???????????????name="preferenceCustomization"
?9
???????????????value="plugin_customization.ini"/>
10
??????</product>
11
</extension>

?2

?3

?4

?5

?6

?7

?8

?9

10

11

可見,我們為我們的產品添加了一個prefereneCustomization屬性,該屬性的值為plugin_customization.ini文件,在該文件中,我們可以配置我們的樣式。在這里,它的內容如下:
1
org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
2
org.eclipse.ui/DOCK_PERSPECTIVE_BAR=topRight

2

事實上,在這個文件中可以定義的參數有上百個,大家可以查看Eclipse的文檔。
這個時候,效果應該是這樣的了:
好了,我們現在對以上的代碼做一個總結。我不是寫教科書,在Blog中也沒有寫得那么詳細的條件。我們這里主要關注在哪個地方對代碼進行擴展,可以達到我們想要的效果。比如,我們要創建視圖,就是需要擴展org.eclipse.ui.part.ViewPart類,然后向其中添加控件,再然后配置plugin.xml文件,最后修改透視圖的代碼,以便它能夠顯示出來。
在ViewPart類中,我們添加控件的操作主要是在public void createPartControl(Composite parent)這個方法中進行,而方法最后會調用以下三個方法:
createActions();
initializeToolBar();
initializeMenu();
從這三個方法的方法名我們不難看出,它們的功能是創建視圖特有的菜單欄和工具欄的,結合上一小節的內容,我們應該很快就可以探索到怎么給視圖添加漂亮的工具欄了,這里我不再羅嗦。
再來看Perspective.java,不難發現,所有的透視圖類都需要實現IPerspectiveFactory接口,而該接口的createInitialLayout方法,就是描述工作臺窗口中編輯器和視圖的布局。默認情況下,透視圖中只包含一個編輯器區域,就是我們第一節中看到的那個效果。在createInitialLayou中,我們可以通過以下幾個方法向透視圖中添加視圖、編輯器和菜單:
addView?? —— 添加視圖
addActionSet —— 添加菜單和工具欄
createFolder —— 創建一個IForderLayou,可以讓多個視圖重疊在同一個位置
寫到這里,肯定有人會問,如果我要創建一個象Eclipse中的資源視圖這樣的視圖,該怎么做呢?這我們就要感謝org.eclipse.jface.viewers包了,Viewer,這里翻譯為查看器,它和視圖是不一樣的。JFace查看器是Jface對SWT部件的封裝,它簡化了我們對小部件的操作。在使用查看器的時候,它的數據使用單獨的模型對象來保存,使用查看器的setInput方法可以為查看器設置模型,此外,在使用查看器的時候,需要為它提供ContentProvider(內容提供器)和LabelProvider(標簽提供器)。
JFace查看器主要分為以下幾類:
1. ListViewer: 對應于SWT的列表控件,目的是將列表中的元素映射至SWT列表控件
2. TreeViewer: 對應于SWT的樹控件,提供樹的展開和折疊等基本操作
3. TableViewer: 對應于SWT的表控件,映射表中的元素
4. TextViewer: 對應于SWT的StyledText控件,創建編輯器的時候,使用這個查看器是最合適不過了。
好了,介紹性的文字就寫到這里,我想大家一定已經知道了探索的方向。下面,我們看一個簡單的示例,就是這篇文章開頭給出的效果圖。它是我模仿醫院管理系統做的一個簡單例子,左邊的視圖就是使用了一個ListView查看器。這里給出它的關鍵代碼:
?1
public?void?createPartControl(Composite?parent)?
{
?2
????????
?3
?4
????????viewer?=?new?ListViewer(parent,?SWT.BORDER);
?5
????????viewer.setContentProvider(new?PersonContentProvider());
?6
????????viewer.setLabelProvider(new?PersonLabelProvider());
?7
????????viewer.setInput(new?PersonModel());
?8
????????
?9
????????createActions();
10
????????initializeToolBar();
11
????????initializeMenu();
12
????}



?2

?3

?4

?5

?6

?7

?8

?9

10

11

12

可以看到,這里需要設置內容提供器和標簽提供器和模型。下面,我們先創建一個病人類Person.java:
?1
package?cn.blogjava.youxia.views;
?2
?3
public?class?Person?
{
?4
????
?5
????private?String?name;
?6
????private?String?sex;
?7
????public?String?getName()?
{
?8
????????return?name;
?9
????}
10
????public?void?setName(String?name)?
{
11
????????this.name?=?name;
12
????}
13
????public?String?getSex()?
{
14
????????return?sex;
15
????}
16
????public?void?setSex(String?sex)?
{
17
????????this.sex?=?sex;
18
????}
19
20
}

?2

?3



?4

?5

?6

?7



?8

?9

10



11

12

13



14

15

16



17

18

19

20

下面,創建模型類PersonModel.java,在構造函數中我們向List中填入了幾個初始化數據:
?1
package?cn.blogjava.youxia.views;
?2
import?java.util.ArrayList;
?3
?4
public?class?PersonModel?
{
?5
????
?6
????private?ArrayList<Person>?list?=?new?ArrayList<Person>();
?7
????
?8
????public?interface?Listener
{
?9
????????public?void?add(Person?p);
10
????????public?void?remove(Person?p);
11
????}
12
????
13
????private?Listener?listener;
14
????
15
????public?PersonModel()
{
16
????????//向list里面填入幾個初始化數據
17
????????Person?p1?=?new?Person();
18
????????p1.setName("病人1");
19
????????p1.setSex("男");
20
????????list.add(p1);
21
????????
22
????????Person?p2?=?new?Person();
23
????????p2.setName("病人2");
24
????????p2.setSex("女");
25
????????list.add(p2);
26
????????
27
????}
28
29
????public?void?setListener(Listener?listener)
{
30
????????this.listener?=?listener;
31
????}
32
????
33
????public?void?add(Person?p)
{
34
????????list.add(p);
35
????????if(listener?!=?null)
{
36
????????????listener.add(p);
37
????????}
38
????}
39
????
40
????public?void?remove(Person?p)
{
41
????????list.remove(p);
42
????????if(listener?!=?null)
{
43
????????????listener.remove(p);
44
????????}
45
????}
46
????
47
????public?ArrayList?elements()
{
48
????????return?list;
49
????}
50
}

?2

?3

?4



?5

?6

?7

?8



?9

10

11

12

13

14

15



16

17

18

19

20

21

22

23

24

25

26

27

28

29



30

31

32

33



34

35



36

37

38

39

40



41

42



43

44

45

46

47



48

49

50

在這里,我們還定義了一個Listener接口,為什么要有這么一個接口呢?就是為了讓我們模型中的數據被改變時,查看器能夠相應更改。下面,我們實現內容提供器,該內容提供器實現了PersonModel中定義的Listener接口,如下PersonContentProvider.java:
?1
package?cn.blogjava.youxia.views;
?2
?3
import?org.eclipse.jface.viewers.IStructuredContentProvider;
?4
import?org.eclipse.jface.viewers.Viewer;
?5
import?org.eclipse.jface.viewers.ListViewer;
?6
?7
import?cn.blogjava.youxia.views.PersonModel.Listener;
?8
?9
public?class?PersonContentProvider?implements?IStructuredContentProvider,
10
????????Listener?
{
11
12
????PersonModel?input;
13
????ListViewer?viewer;
14
????
15
????public?Object[]?getElements(Object?inputElement)?
{
16
????????//?TODO?自動生成方法存根
17
????????return?input.elements().toArray();
18
????}
19
20
????public?void?dispose()?
{
21
????????//?TODO?自動生成方法存根
22
????????if(input?!=?null)
{
23
????????????input.setListener(null);
24
????????}
25
????????input?=?null;
26
27
????}
28
29
????public?void?inputChanged(Viewer?viewer,?Object?oldInput,?Object?newInput)?
{
30
????????//?TODO?自動生成方法存根
31
????????viewer?=?(ListViewer)viewer;
32
????????input?=?(PersonModel)newInput;
33
????????input.setListener(this);
34
35
????}
36
37
????public?void?add(Person?p)?
{
38
????????//?TODO?自動生成方法存根
39
????????viewer.add(p);
40
????}
41
42
????public?void?remove(Person?p)?
{
43
????????//?TODO?自動生成方法存根
44
????????viewer.remove(p);
45
????}
46
47
}

?2

?3

?4

?5

?6

?7

?8

?9

10



11

12

13

14

15



16

17

18

19

20



21

22



23

24

25

26

27

28

29



30

31

32

33

34

35

36

37



38

39

40

41

42



43

44

45

46

47

我們知道,列表中的元素都是Person類的對象,怎么讓他們顯示出來呢,需要實現標簽提供器,在標簽提供器中,我們可以設置對象顯示的圖標和文字,如下PersonLabelProvider.java:
?1
package?cn.blogjava.youxia.views;
?2
?3
import?org.eclipse.jface.viewers.ILabelProvider;
?4
import?org.eclipse.jface.viewers.ILabelProviderListener;
?5
import?org.eclipse.swt.graphics.Image;
?6
?7
public?class?PersonLabelProvider?implements?ILabelProvider?
{
?8
?9
????public?Image?getImage(Object?element)?
{
10
????????return?null;
11
????}
12
13
????public?String?getText(Object?element)?
{
14
????????//?TODO?自動生成方法存根
15
????????return?((Person)element).getName();
16
????}
17
18
????public?void?addListener(ILabelProviderListener?listener)?
{
19
????????//?TODO?自動生成方法存根
20
21
????}
22
23
????public?void?dispose()?
{
24
????????//?TODO?自動生成方法存根
25
26
????}
27
28
????public?boolean?isLabelProperty(Object?element,?String?property)?
{
29
????????//?TODO?自動生成方法存根
30
????????return?false;
31
????}
32
33
????public?void?removeListener(ILabelProviderListener?listener)?
{
34
????????//?TODO?自動生成方法存根
35
36
????}
37
38
}

?2

?3

?4

?5

?6

?7



?8

?9



10

11

12

13



14

15

16

17

18



19

20

21

22

23



24

25

26

27

28



29

30

31

32

33



34

35

36

37

38

運行程序,就得到了文章開頭的效果,但是不能在右邊的視圖中顯示病人的詳細信息。
如果要做到視圖的交互,需要添加事件的監聽器。使用Java 進行GUI開發的人應該都不會陌生,而我在RCP上,也處于探索階段,更深一步的內容,讓我們自己慢慢研究吧。