可以毫無顧慮地說,在未來幾年中,對移動設備應用程序的需求將越來越多。 現在是學習 eJFace 的好時機,eJFace 是開放標准的嵌入式 JFace 庫,它是構 建嵌入式應用程序的一項新技術。嵌入式 JFace(Embedded JFace,eJFace)是 嵌入式富客戶端平台(embedded Rich Client Platform,eRCP)的組件,它為開 發人員提供了一個嵌入式環境,用於組合嵌入式應用程序的用戶界面 (UI)。
eJFace 包含一些庫,使用這些庫可以構建應用程序而無需進行復雜的 eSWT 編程。它將提供強大的 API 並引入 Model-View-Controller (MVC) 架構, 用於輕松地實現和維護嵌入式應用程序。在本文中,我們將說明如何用 eJFace 開發應用程序,並比較 eJFace 與 JFace。本文將幫助熟悉 JFace 的開發人員了 解 eJFace 與 JFace 之間的差異,並減少開發 eJFace 應用程序所需的時間。
您將學習以下內容:
eJFace 庫的結構、eJFace 庫的 API 及其用 法
JFace 與 eJFace 之間的差異
如何在 eRCP 環境下開發 eJFace 、eSWT 和 eWorkbench 應用程序
如何向應用程序中添加 eJFace 功能
概覽
我們先簡要回答一下開發人員最初看到 eJFace 時會問到的 三大問題。
1. eJFace 是什麼?
eJFace 專門用於手持設備並且是 桌面型 JFace 庫的純子集。
擴展 eSWT 並與之進行互操作的不依賴於平 台的用戶界面 API。
集成了一些 eSWT 小部件以提供許多有用功能,例如 基於 MVC 的查看器,它可用於減少開發和維護工作。
排除 JFace 庫中體 積龐大、在手持設備上沒有優勢的部分。
2. eJFace 的用途是什麼?
eJFace 庫將提供對於嵌入式設備有用的高級 UI 功能。
創建與 eWorkbench 集成的 eRCP 應用程序。
提供了一組類,這組類用於擴展 eSWT 以使 eRCP 應用程序可以與 eRCP 工作台集成並提供更復雜的小部件(例如 面向 MVC 的查看器)。
3. eJFace 的特性是什麼?
eSWT 與 eJFace 之間的關系就像 SWT 與 JFace 之間的關系一樣。
eJFace 依賴於 eSWT 的 Core 和 Expanded 部分以及 Java 2, Micro Edition (J2ME) 連接設備 配置(Connected Device Configuration,CDC)的配置文件。
它在查看器中把 eSWT 小部件打包到 MVC 范例的上下文中。它將隱藏許多實 現細節並減少代碼行數。
它構建於 eSWT 之上,並且無需使用附加本地庫 就可以運行。
它將提供一個允許高效處理資源以節約內存並提高性能的資 源處理類。
eJFace 包及詳細信息
表 1. eJFace 中受支持的包
包
org.eclipse.jface.action
支持共享 UI 資源,例如菜單、工具欄和狀態行
org.eclipse.jface.operation
JFace 支持長期運 行的操作
org.eclipse.jface.preference
首選項框 架
org.eclipse.jface.resource
支持管理資源(例 如 SWT 字體和圖像)
org.eclipse.jface.util
構 建 JFace 中隨處使用的塊(包括屬性更改事件、偵聽程序列表實現和運行時檢查 的斷言)
org.eclipse.jface.viewers
查看器框架 ,這些查看器都是用於 SWT 小部件、基於模型的內容適配器
正如前面提到的,eJFace 將刪除 JFace 的大量包和 庫,這些包和庫都是面向桌面的並且不適用於手持設備。鑒於要求所使用的包和 庫占用較少內存並且為了降低實現復雜度,eJFace 提供了上面所示的包。要獲得 關於每個包的 API 的詳細信息,請參考 eJFace Java 文檔。
下面是表 1 中提到的包摘要。
org.eclipse.jface.action
org.eclipse.jface.action 包用於通過響應用戶操作來與用戶進行互動。org.eclipse.jface.action 包僅支持向狀態行中添加條目。但是,建議將 Action 包與 eSWT 命令小部件結合使用,因為命令小部件更易於使用。選擇在附帶的小部件獲得焦點時顯示的動態菜單。有關更多信息,請參閱樣例應用程序中提供的示例命令小部件。
org.eclipse.jface.operation
eJface 刪除了 JFace org.eclipse.jface.operation 包中除了 IRunnableWithProgress 接口以外的幾乎所有功能。IRunnableWithProgress 接口適於由執行長期運行的操作的類來實現。長期運行的操作通常是由顯示進度指示器以及 Cancel 按鈕或進度條的模式對話框顯示的。
org.eclipse.jface.preference
org.eclipse.jface.preference 只提供 PreferencePage 和 PreferenceStore 庫。PreferencePage 是用於顯示消息或請求獲得有限信息的臨時對話框的一次性使用資源。PreferencePage 將阻止運行其他 eRCP 應用程序,直至 PreferencePage 被關閉,這將確保在執行主程序之前先收集信息。PreferenceStore 用於保存應用程序的信息。PreferenceStore 將生成一個屬性文件以幫助應用程序存儲一些有用信息。PreferencePage 和 PreferenceStore 通常用於保存從用戶輸入中收集到的用久信息。PreferencePage 樣例應用程序顯示如何實現提示以收集用戶信息和存儲內容。
org.eclipse.jface.resource
顧名思義,org.eclipse.jface.resource 包將管理資源,例如圖像、顏色、和字體信息。它使您可以輕松地找到特定資源。另外:
ImageRegistry 和 ImageDescriptor 庫用於維護符號顏色名稱與 SWT 顏色之間的映射。受支持的圖像格式依賴於平台。
JFaceColors 用於 獲得並存儲設備的默認顏色。
FontRegistry 和 FontDescriptor 用於維 護符號字體名稱與 SWT 字體之間的映射。
CompositeImageDescriptor 是 圖像描述符的抽象類,可以通過其他圖像合成一張圖像以模擬自定義圖形的效果 。
JFaceResource 是用於訪問特定於 eJFace 資源的實用程序方法。
StringConverter 將輕松地在各種數據類型與字符串之間進行轉換。
org.eclipse.jface.util org.eclipse.jface.util 將提供增強 eSWT 應 用(包括屬性更改事件、事件偵聽程序收集機制和運行時斷言檢查)的有用方法 。org.eclipse.jface.viewers org.eclipse.jface.viewers 只包括 TreeViewer 和 TableViewer。這些查看器是基於 MVC 架構的,用於把內部功能與界面外觀分 隔開來。這將使您可以輕松地維護和擴展 eJFace 查看器。另外:
TreeViewer 是由顯示用戶展開和折疊節點和子節點的層次結構數據的 eSWT 樹型小部件來實現的。
在構建 TreeViewer 之後,您必須通過實現 ITreeContentProvider 接口來確定 TreeViewer 的內容。
通過實現 ILabelProvider 接口來確定顯示內容的方法。
通過使用指定內容和標簽 提供程序將其傳遞給數據的根節點。
TableViewer 是由用於顯示列數據與 行數據的 eSWT 表小部件實現的。Table 和 TableItem 可用於完成 TableViewer 的功能。
類似於 TreeViewer,您將首先創建 TableViewer,然後相應地 設定內容提供程序。
設定標簽提供程序。
設定輸入。
下載 中的 eJFace org.eclipse.jface.viewers 演示應用程序將顯示如何實現 TreeViewer 和 TableViewer。
eJFace 與 JFace 之間的差異
正如 前面提到的,eJFace 是 JFace 的嚴格子集。將刪除或減少相當一部分不太可能 用在嵌入式設備上的庫。表 2 匯總了 eJFace 與 JFace 之間的主要差異。
表 2. eJFace 與 JFace 的差異
eJFace 與 JFace 比較
從 JFace 中刪除的包
org.eclipse.jface.dialogs
org.eclipse.jface.operation (eJFace 將只提供 IRunnableWithProgress 接口)
org.eclipse.jface.window
org.eclipse.jface.wizard
JFace 中減少的包
org.eclipse.jface.action
org.eclipse.jface.preference (eJFace 將只提供 PreferencePage 類)
org.eclipse.jface.viewers (eJFace 將只提供 TreeViewer 和 TableViewer)
未更改的 包
org.eclipse.jface.resource
org.eclipse.jface.util
您可能想知道為什麼把 jface.wizard、jface.dialogs 和 jface.window 從 JFace 中刪除。原因有兩個 :首先,現有對話框、向導和窗口代碼都是面向桌面的,並且需要進行大量的修 改工作才能由移動設備使用。例如,手機中的對話框通常不應使用按鈕,因為手 機可能沒有光標和鼠標。其次,所選包都是應用程序可以輕松實現的便利函數, 而不是復雜代碼或通用代碼。
您可能還希望了解 eJFace 代碼不在 eSWT Mobile Extensions 中使用命令類的原因。我們不希望讓 eJFace 依賴於 Mobile Extensions,因為它應該是 eRCP 中的可選組件。此外,Mobile Extensions 將 提供 QueryDialog 和 TimedMessageBox,用於把一些 JFace 對話框替代為相應 的移動版本。
對 org.eclipse.jface.action 的更改要求提供說明。 JFace 僅支持向狀態行中添加條目。由於 eWorkbench 不提供常見的菜單欄函數 ,因此將從 eJFace 中刪除大多數操作類。不過,將在 eSWT 的 Mobile Extensions 中把操作條目替換為命令類。
eJFace org.eclipse.jface.viewers 演示應用程序
eJFace 只提供 TreeViewer 和 TableViewer。
TreeViewer
要設計 TreeViewer 演示應用程序 ,您必須創建節點類作為數據模型。在這裡,我們將創建兩個名為 NBATeamNode 和 NBAPlayer 的節點類。接下來,您必須定義節點之間的關系。例如, NBATeamNode 可以添加其他 NBATeamNode 或 NBAPlayer 實例。您必須在 NBATeamNode 中定義兩個單獨的 ArrayLists 才能添加。
清單 1. 定義節 點類及其父子節點關系
public class NBATeamNode {
private String name;
private ArrayList teams = new ArrayList();
private ArrayList players = new ArrayList ();
private NBATeamNode parent;
public NBATeamNode(String n){
name = n;
}
protected Object getParent(){
return parent;
}
public NBATeamNode addTeam(NBATeamNode child){
teams.add (child);
child.parent = this;
return this;
}
public NBATeamNode addPlayer(NBAPlayer child){
players.add(child);
child.parent = this;
return this;
}
public ArrayList getteams(){
return teams;
}
public ArrayList getplayers(){
return players;
}
public String toString(){
return name;
}
public class NBAPlayer {
private String name;
NBATeamNode parent;
public NBAPlayer(String n){
name = n;
}
protected Object getParent(){
return parent;
}
public String toString(){
return name;
}
在擴展 org.eclipse.ercp.eworkbench.applications 之後,我們將創建 TreeViewer 實 例並與生成的 SampleView 類的 createPartControl 方法中的當前復合內容關聯 起來。然後設定此樹的期望布局並向此 TreeViewer 中添加樹內容提供程序和樹 標簽提供程序實例。內容提供程序將提供所有樹的父子節點關系,而標簽提供程 序將提供每個元素所表示的圖像和文本。最後,為這個 TreeViewer 給定一個輸 入節點。記住,此輸入節點應當是數據模型的根節點。例如,我們將先創建根節 點並向其中添加三個 NBATeamNode 作為另一個球隊名稱。然後,我們將使用變量 NBAPlayer 將五個首發上場的 NBA 球員添加到每個球隊中。正如您可以看到的那 樣,我們把名為 “root” 的根 NBATeamNode 輸入到 TreeViewer 中 。
清單 2. SampleView 類
public void createPartControl (Composite parent){
composite= new Composite (parent,SWT.NONE);
composite.setLayout(new GridLayout (1,false));
treeviewer = new TreeViewer(composite);
treeviewer.getTree().setLayoutData(new GridData (GridData.FILL_BOTH));
treeviewer.setContentProvider(new SampleTreeContentProvider());
treeviewer.setLabelProvider(new SampleTreeLabelProvider());
treeviewer.setInput(getInput());
treeviewer.expandAll();
}
private NBATeamNode getInput(){
NBATeamNode root = new NBATeamNode("root");
NBATeamNode team1= new NBATeamNode("Houston Rockets");
NBATeamNode team2= new NBATeamNode("LA Lakers");
...
root.addTeam(team1);
root.addTeam(team2);
...
team1.addPlayer(new NBAPlayer("Yao Ming"));
team1.addPlayer(new NBAPlayer("Tracy McGrady"));
...
return root;
}
樹內容提供程序必須實現 ITreeContentProvider。使用 getParent 和 getChildren 方法定義此樹的父子 節點關系。最後,使用 getElements 方法獲得每個元素的子元素。
清單 3. TreeViewerContentProvider
public class SampleTreeContentProvider implements ITreeContentProvider {
//other methods are not mentioned here are unchanged
public Object[] getChildren(Object arg0) {
if(arg0 instanceof NBATeamNode) {
NBATeamNode node = (NBATeamNode)arg0;
return concat(node.getteams().toArray (),node.getplayers().toArray());
}
return EMPTY_ARRAY;
}
protected Object[] concat(Object[] object, Object[] more) {
Object[] both = new Object [object.length + more.length];
System.arraycopy(object, 0, both, 0, object.length);
System.arraycopy(more, 0, both, object.length, more.length);
return both;
}
public Object getParent(Object arg0) {
return ((NBATeamNode) arg0).getParent();
}
public Object[] getElements(Object arg0) {
return getChildren(arg0);
}
樹標簽提供程序必須實現 ILabelProvider。正如您可以看到 的那樣,我們將使用 getImage 和 getText 方法定義每個節點所表示的圖像和文 本。
清單 4. TreeViewerLabelProvider
public class SampleTreeLabelProvider implements ILabelProvider {
//other methods are not mentioned here are unchanged
private ArrayList listeners;
private Image Team, Player;
public SampleTreeLabelProvider(){
listeners = new ArrayList();
Team = new Image(null, getClass ().getResourceAsStream("/res/file.png"));
Player= new Image (null, getClass().getResourceAsStream("/res/folder.png"));
}
public Image getImage(Object arg0) {
if(arg0 instanceof NBATeamNode){
return Team;
}else{
return Player;
}
}
public String getText(Object arg0) {
if(arg0 instanceof NBATeamNode) {
return ((NBATeamNode)arg0).toString();
}else {
return ((NBAPlayer)arg0).toString();
}
}
public void dispose() {
if(Team != null) Team .dispose();
if(Player != null) Player.dispose();
}
}
當您把此演示應用程序部署到設備上的 eWorkbench 中後 ,您將看到圖標顯示在名為 Test TreeViewer Sample 的應用程序列表中。在命 令窗口中單擊 Open 來啟動它。那時,您將找到我們創建的樹。您可以擴展每個 球隊並可以在球隊名冊中看到相應的球員。
圖 1. 設備上 eWorkbench 中 的 TreeViewer 演示應用程序
TableViewer
要設計 TableViewer 演示應用程序,您必須創建 數據模型類。在這裡,將創建 Book.java。如您所見,有五個屬性需要輸出到表 列中。因此,您必須為每個屬性使用 getter-setter 方法以供進一步使用。
清單 5. 定義數據模型類
public class Book {
String name;
String isbn;
String publisheddate;
String price;
String available;
public String getAvailable() {
return available;
}
public void setAvailable(String available) {
this.available = available;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getPublisheddate() {
return publisheddate;
}
public void setPublisheddate(String publisheddate) {
this.publisheddate = publisheddate;
}
}
在擴展 org.eclipse.ercp.eworkbench.applications 之後,我們將創建 TableViewer 實例並將其與 SampleView 類中的當前合成的 createPartControl 方法關聯起來。然後設定期望的布局。但是在向此表查看器 中添加內容提供程序和標簽提供程序實例之前,我們必須先創建表。表包括適當 的列數和相應名稱。打包每個列並使其顯示在表中。最後,設定 table content provider 和 table label provider 並提供此 TableViewer 輸入(換言之,為 它提供數據)。記住,此輸入必須是數據模型的 ArrayList。例如,先創建 ArrayList 並向其中添加三個書實例。將根據內容提供程序類和標簽提供程序類 設定表中字段的值。
清單 6. SampleView 類
public void createPartControl(Composite parent) {
composite= new Composite(parent,SWT.NONE);
composite.setLayout(new GridLayout (1,false));
tableviewer = new TableViewer (composite);
Table table = tableviewer.getTable();
table.setLayoutData(new GridData(GridData.FILL_BOTH));
column0 = new TableColumn(table,SWT.LEFT,0);
column0.setText("Books Name");
column1 = new TableColumn(table,SWT.LEFT,1);
column1.setText("ISBN");
column2 = new TableColumn (table,SWT.LEFT,2);
column2.setText("Published Date");
column3 = new TableColumn(table,SWT.LEFT,3);
column3.setText ("Price");
column4 = new TableColumn(table,SWT.LEFT,4);
column4.setText("Available Now?");
for(int i =0, n=table.getColumnCount();i<n;i++){
table.getColumn (i).pack();
}
table.setHeaderVisible(true);
table.setLinesVisible(true);
tableviewer.setContentProvider(new SampleTableContentProvider());
tableviewer.setLabelProvider( new SampleTableLabelProvider());
tableviewer.setInput(getInput());
}
private ArrayList getInput() {
Book b1 = new Book();
Book b2 = new Book();
Book b3 = new Book();
b1.setName("Red Book");
b1.setIsbn("U2w3e4r5t6y");
b1.setPublisheddate("1980-08-28");
b1.setPrice("$1000");
b1.setAvailable("Yes");
b2.setName("Blue Book");
b2.setIsbn("U1q2w3e4r");
...
return Books;
}
TableViewerContentProvider 必須實現 IStructuredContentProvider 接口。TableViewerContentProvider 將定義此表 的顯示關系。正如您可以在此類中看到的那樣,我們將使用 getElements 方法獲 得一個特定數組的每條數據,該數組可以表示書名,也可以表示價格。
清 單 7. TableViewerContentProvider
public class SampleTableContentProvider implements IStructuredContentProvider {
//other methods are not mentioned here are unchanged
public Object[] getElements(Object arg0) {
return ((ArrayList)arg0).toArray();
}
}
TableViewerLabelProvider 必須實現 ITableLabelProvider 接 口。TableViewerLabelProvider 將定義此表中每列的文本或圖像。我們可以使用 getColumnText 方法獲得每個元素的文本(在這裡,我們並未實現 getColumnImage 方法)。
清單 8. TableViewerLabelProvider
public class SampleTableLabelProvider implements ITableLabelProvider {
//other methods are not mentioned here are unchanged
public Image getColumnImage(Object arg0, int arg1) {
return null;
}
public String getColumnText(Object arg0, int arg1) {
String result = "";
Book book = (Book) arg0;
switch(arg1){
case 0:
result = book.getName();
break;
case 1:
result = book.getIsbn();
break;
case 2:
result = book.getPublisheddate();
break;
case 3:
result = book.getPrice();
break;
case 4:
result = book.getAvailable();
break;
}
return result;
}
public boolean isLabelProperty(Object arg0, String arg1) {
return false;
}
}
當您把此演示應用程序部署到 eWorkbench 設備中後,您將看到圖標顯示在名為 Test TableViewer Sample 的 應用程序列表中。在命令窗口中單擊 Open 以啟動它。您將找到我們創建的表。
圖 2. 設備上的 eWorkbench 中的 TableViewer 演示應用程序
eJFace org.eclipse.jface.preference 演示應用程序
PreferencePage
eJFace 只提供 PreferencePage 來存儲您所需的 必備首選項數據,例如服務器信息、用戶名和密碼。而且,它僅在目標為 eWorkbench 時才能運行。在圖 3 中,我們將展示如何開發一個簡單的首選項應 用程序,包括 OK、Cancel 和 Restore Default 按鈕。
清單 9. 添加到 plugin.xml
<extension point="org.eclipse.ui.preferencePages">
<page
class="preferencesample.PrefPageOne"
id="preferenceSample.page1"
name="Server authentication"/>
</extension>
您的首選項頁 面類必須擴展 PreferencePage 並實現 IWorkbenchPreferencePage 以使您的首 選項頁面顯示在 eWorkbench 中。首先,聲明必需的變量,包括 String、Text、 Label、Button 和 PreferenceStore。PreferenceStore 將存儲您鍵入的名稱-值 對。createContents 方法用於顯示用戶的首選項。
首先,先創建一個合 成的首選項頁面並用 GridLayout 設定布局。其次,用一個惟一名稱創建 PreferenceStore 並通過這個 PreferenceStore 裝入數據。再次,創建三個允許 用戶鍵入所需值的文本字段。值包括服務器地址、用戶名和密碼。使用 SetDefaultValue() 來設定這些字段的默認值。當用戶打開首選項頁面時,他們 將看到這些默認值。
使用 performDefaults 將重置默認值。使用 performOK 將在您單擊 OK 時保存鍵入的值。使用 performCancel 將在您單擊 Cancel 時不保存任何更改退出此首選項頁面。當首選項頁面實現 IWorkbenchPreferencePage 時,init(IWorkbench arg0) 是必須實現的必備方法 。
清單 10. 首選項頁面樣例代碼
public class PrefPageOne extends PreferencePage implements IWorkbenchPreferencePage{
private static final String SERVERADDR = "SERVERADDR";
private static final String USERNAME = "USERNAME";
private static final String USERPASSWORD = "USERPASSWORD";
private Text fieldOne;
private Text fieldTwo;
private Text fieldThree;
Label label1, label2, label3;
Composite composite;
Button defaultbutton;
PreferenceStore preferenceStore;
protected Control createContents(Composite parent){
composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2,false));
preferenceStore = new PreferenceStore("com.ibm.test.ejface.preference");
try {
preferenceStore.load();
}catch (IOException e) {}
label1 = new Label(composite, SWT.LEFT);
label1.setText("Server address:");
label1.setground(new Color(composite.getDisplay(),0x66, 0xCC, 0xFF));
fieldOne = new Text(composite, SWT.SINGLE | SWT.BORDER);
fieldOne.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
label2 = new Label(composite, SWT.LEFT);
label2.setText("Username:");
fieldTwo = new Text(composite, SWT.SINGLE | SWT.BORDER);
fieldTwo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
label3 = new Label(composite, SWT.LEFT);
label3.setText("Password:");
fieldThree = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD);
fieldThree.setLayoutData(new GridData (GridData.FILL_HORIZONTAL));
SetDefaultValue();
fieldOne.setText(preferenceStore.getString(SERVERADDR));
fieldTwo.setText(preferenceStore.getString(USERNAME));
fieldThree.setText(preferenceStore.getString(USERPASSWORD));
defaultbutton = new Button(composite,SWT.PUSH | SWT.LEFT);
defaultbutton.setText("Restore to Default value");
defaultbutton.addSelectionListener(new SelectionListener(){
public void widgetSelected (SelectionEvent e) {
performDefaults();
}
public void widgetDefaultSelected(SelectionEvent e) {
}});
return composite;
}
protected void performDefaults(){
fieldOne .setText (preferenceStore.getDefaultString(SERVERADDR));
fieldTwo .setText(preferenceStore.getDefaultString(USERNAME));
fieldThree.setText(preferenceStore.getDefaultString(USERPASSWORD));
}
public boolean performOk(){
if(fieldOne != null && fieldOne .getCharCount() != 0)
preferenceStore.setValue(SERVERADDR, fieldOne .getText());
if(fieldTwo != null && fieldTwo .getCharCount() != 0)
preferenceStore.setValue(USERNAME, fieldTwo .getText());
if(fieldThree != null && fieldThree.getCharCount() != 0)
preferenceStore.setValue(USERPASSWORD, fieldThree.getText());
try{
preferenceStore.save();
} catch (IOException e) {
return false;
}
return true;
}
private void SetDefaultValue() {
if (fieldOne != null && fieldOne.getCharCount() == 0) {
preferenceStore.setDefault(SERVERADDR, "www.ibm.com");
}
if (fieldTwo != null && fieldTwo.getCharCount() == 0) {
preferenceStore.setDefault(USERNAME, "Administrator");
}
if (fieldThree != null && fieldThree.getCharCount() == 0) {
preferenceStore.setDefault(USERPASSWORD, "admin");
}
}
public boolean performCancel() {
composite.dispose();
this.dispose ();
return true;
}
public void init (IWorkbench arg0) {
}
}
在把此演示應用程序部 署到 eWorkbench 設備中後,您將看到圖表顯示在 Preference Demo Application 列表中。單擊 OK 以保存輸入內容,單擊 Cancel 以退出首選項頁 面,或者單擊 Restore 以將每個文本字段的值重設為默認值。
圖 3. eWorkbench 設備中的首選項頁面演示應用程序
eJFace org.eclipse.jface.resource 演示應用程序
eJFace 只提供 重要的 org.eclipse.jface.resource 包庫。在演示應用程序中,我們將演示如 何使用 ImageRegistry 和 fontRegistry 以高效地管理圖像和字體對象。還引入 了 JFaceColors 以幫助管理相應小部件的顏色。此外,我們將展示如何使用命令 小部件以實現 org.eclipse.jface.action 功能。
清單 11 中列出了演示 代碼,這段代碼將使用注冊表把字體、顏色和圖像設定到相應的小部件中。我們 還將展示如何構造 eSWT 命令小部件。此外,它只在目標為 eWorkbench 中的應 用程序時才運行。
ImageRegistry 用於存儲和裝入不同的圖像。使用 put() 和 get() 方法,您可以輕松地把名稱分配給圖像和管理許多圖像。 FontRegistry 類似於 ImageRegistry 並用於存儲和裝入不同的 fontData。使用 put 和 get 方法,用戶可以高效地管理字體。JFaceResources 可用於在整個程 序中管理 ImageRegistry 和 FontRegistry。
JFaceColors 可以把特定顏 色動態指派給小部件的前景和背景。StringConverter 將提供 Java 字符串處理 功能。在此演示應用程序中,我們將使用它把字符串對象分割為 StringArray。
命令小部件是一個有用的 eSWT API。命令僅在附帶的小部件獲得焦點時 顯示。在本樣例中,RecoverCommand 附帶了合成對象。RecoverCommand 在合成 對象獲得焦點時顯示。否則,RecoverCommand 將消失。我們將向 RecoverCommand 中添加 SelectionListener。當 RecoverCommand 被選中時,將 調用 widgetSelected。
下面是設備上的資源演示樣例。
清單 11. 資源樣例代碼
//ImageRegistry demo
ImageRegistry ir = new ImageRegistry();
ir.put("img1",new Image(display,getClass ().getResourceAsStream("/icons/ibm1.png")));
ir.put("img2",new Image(display,getClass().getResourceAsStream("/icons/ibm2.png")));
Label Imagelabel = new Label (composite, SWT.LEFT);
Imagelabel.setImage(ir.get("img1"));
//FontRegistry demo
FontRegistry fr = new FontRegistry(composite.getDisplay ());
FontData[] fd = new FontData[2];
fd[0]= new FontData("Tacoma",20, SWT.NORMAL);
fd[1]= new FontData("Times New Roman",12, SWT.NORMAL);
fr.put("SysFont", fd);
Label Fontlabel = new Label (composite, SWT.LEFT);
Fontlabel.setText("FontRegistry");
Font normalfont = new Font(composite.getDisplay(),fr.getFontData("SysFont")[0]);
Fontlabel.setFont(normalfont);
JFaceResources.setFontRegistry (fr);
Font font = new Font(display, JFaceResources.getFontRegistry().getFontData
("SysFont")[1]);
//JFaceColors demo
Label JFaceColorslabel = new Label (composite, SWT.LEFT);
JFaceColorslabel.setText ("JFaceColors");
JFaceColors.setColors(JFaceColorslabel, composite.getDisplay().getSystemColor
(SWT.COLOR_DARK_YELLOW), composite.getDisplay().getSystemColor (SWT.COLOR_BLUE));
String[] stringArray = StringConverter.asArray("eJface Developer Works");
Command RecoverCommand = new Command(composite, Command.OK, 0);
RecoverCommand.setText("Default Setting");
RecoverCommand.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
Imagelabel.setImage(ir.get("image1"));
Imagelabel.redraw();
Fontlabel.setFont(font);
Fontlabel.redraw();
stringButton.setText("eJface Developer Works");
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
圖 4. eJFace 資源樣例(更改前)
圖 5. eJFace 資源樣例(更改後)
eWorkbench 上的 eJFace 集成演示應用程序
現在將把上面所述 的所有子函數集成到一個樣例中。首先,創建一個可以根據選擇顯示 NBA 或 MLB 球員的 TreeViewer。其次,有一個根據您是位於 NBA 頁面還是位於 MLB 頁面顯 示默認值的首選項頁面。再次,可以突出顯示窗口中的一個球隊或球員,然後在 命令窗口中單擊 2005~2006 record。設備將創建一個記錄這條用 TableViewer 創建的記錄的表。由於源代碼全部顯示在這裡會顯得太長,並且此整合樣例中未 添加任何新函數,因此您可以到 下載 中找到源代碼進行進一步研究。圖 6、圖 7 和圖 8 演示了設備上的整合。
圖 6. eWorkbench 中所示的 eJFace 整 合樣例
圖 7. NBA 首選項頁面;默認值是 NBA 的首選項
圖 8. 顯示球員記錄的表
結束語
本文演示了開發 eJFace 應用程序所需的步驟,比較了 JFace 與 eJFace,並且研究了 eJFace 開發背後的原因。在此過程中,回顧了 eJFace 庫的結構、eJFace 庫的 API 及其用法,了解了如何在 eRCP 環境內開發 eJFace、eSWT 和 eWorkbench 應用程序,並且向應用程序中添加了 eJFace 功能 。
本文配套源碼