使用 JFace 工具箱
Jeff Gunther
總經理, Intalgent Technologies
2003 年 9 月 09 日
無論您使用什么語言開發 GUI 應用程序,收集用戶輸入的交互式機制都是不可或缺的。屬于開發中的 Eclipse 項目的 JFace 工具箱提供了一組功能強大的用戶界面組件,開發人員可以輕松地在獨立應用程序中利用這些組件。JFace 工具箱中比較有趣的組件之一是對向導的支持。JFace 向導和標準窗口小部件工具箱(Standard Widget Toolkit,SWT)內的其它用戶界面組件結合起來提供了靈活的機制,以便系統化地收集用戶輸入和執行數據驗證。
過去,用 Java 開發高度交互式的客戶機端應用程序,使這些應用程序看起來就象本機應用程序并且能象本機應用程序那樣操作,這樣的想法就象圣杯(Holy Grail)一樣難以捉摸。隨著 Eclipse 項目的出現,開發人員開始創建模擬原汁原味的本機應用程序的 Java 應用程序。雖然傳統意義上認為 Eclipse 項目是 Java 的開放源碼集成開發環境(IDE),但是該項目涉及的范圍要廣得多。事實上,在 eclipse.org 網站首頁上,Eclipse 被描述為“…一種通用工具平臺 - 是一種開放的可擴展 IDE,它可以做任何事,而不是特別用于某個方面。”
在 Eclipse 平臺開發期間,該項目產生了兩個用戶界面工具箱:SWT 和 JFace。SWT 提供了一個與平臺無關的 API,該 API 與操作系統的本機窗口環境緊密地集成在一起。該工具箱使開發人員不必面對在使用 Java 的抽象窗口工具箱(Abstract Window Toolkit,AWT)或 Java 基礎類(Java Foundation Classes,JFC)時在許多設計和實現方面所要作的權衡。JFace 工具箱是與平臺無關的 API,可與 SWT 進行互操作。該庫提供了一組組件和助手實用程序,它們使開發 SWT 用戶界面中的許多常見任務得以簡化。
盡管在開發本文中的樣本代碼時使用了 Eclipse,但文章本身演示如何在獨立應用程序的上下文內使用 JFace 向導。有關 Eclipse 項目的更多信息或背景知識,請參閱本文后面的 參考資料。
地址簿應用程序
在查看如何使用 JFace 工具箱的代碼和實現細節之前,讓我們查看一下這個示例應用程序的用途和結構。本文所包含的應用程序是一個簡單的內存中的地址簿,它允許用戶添加個人地址簿聯系人。該應用程序包含了一個由兩頁組成的 JFace 向導,每一頁都包含了描述特定聯系人的域。用戶可以使用 圖 1中所示的表來瀏覽聯系人列表。
圖 1. 在 Red Hat Linux 8 上運行的地址簿應用程序
如 圖 2所示,New Contact 向導供用戶創建新的聯系人。
圖 2. 用 Microsoft Windows XP 上的 New Contact 向導來說明數據驗證
就象 Eclipse 項目一樣,SWT 和 JFace 庫一開始就設計成支持各種各樣的操作系統和環境。為演示這些庫的跨平臺能力,已經將所包含的示例獨立應用程序打包,以便能在 Microsoft Windows 和 Linux 上運行。
環境需求
您可以在 參考資料一節中查找并下載本文中所用的代碼。要測試地址簿應用程序,您的環境必須滿足下列最低需求:
- Microsoft Windows XP 或 Red Hat Linux 8 操作系統
- Java 2 SDK,標準版 1.4 或更高版本
- Apache Ant 1.5.2 或更高版本
雖然已經很小心地使 Ant 構建腳本可以跨平臺使用,但是仍然只在 Microsoft Windows XP 和 Red Hat Linux 8 操作系統上測試和驗證了個人地址簿應用程序。讓我們從安裝和設置樣本代碼開始吧。
安裝和構建地址簿應用程序
要安裝和構建地址簿應用程序,請完成下列步驟:
- 下載源代碼軟件包。請參閱 參考資料中的鏈接。
- 將
addressbook.zip
文件解壓縮到臨時目錄中。
- 在新創建的目錄中運行下面這個命令:
ant clean
- 在新創建的目錄中運行下面這個命令:
ant
如果您的環境滿足需求并且配置正確,那么您應當會看到類似于下面這樣的內容:
清單 1. 構建地址簿應用程序
Buildfile: build.xml
init:
[mkdir] Created dir: D:\Address Book\dist
compile-common:
compile-module:
[echo] Compiling ...
[mkdir] Created dir: D:\Address Book\build
[mkdir] Created dir: D:\Address Book\build\classes
[javac] Compiling 8 source files to D:\Address Book\build\classes
package-common:
[jar] Building jar: D:\Address Book\dist\addressbook.jar
default:
BUILD SUCCESSFUL
|
使用 JFace 向導
既然我們已經介紹了 SWT 和 JFace 的基礎知識以及地址簿應用程序的行為,讓我們研究一下如何使用 JFace 向導。由于本文的目的在于介紹 JFace 向導,因此并沒有提供有關如何創建獨立應用程序的更多背景信息。有關如何在 Eclipse 工作臺之外使用 SWT/JFace 組件的更多信息和背景知識,請參閱 Adrian Van Emmenis 的由三部分所組成的文章系列(請參閱 參考資料以獲取鏈接)。
在地址簿應用程序中, NewContactAction
類處理用戶從 File 菜單選擇 New Contact這一操作(請參閱 圖 3)。
圖 3. New Contact 菜單項
清單 2中的代碼說明了為用戶打開一個向導所需的對象和方法。
清單 2. NewContactAction 類
1 public class NewContactAction extends Action
2 {
3 ApplicationWindow window;
4
5 publicNewContactAction(ApplicationWindow w)
6 {
7 window = w;
8 this.setText("New Contact");
9 this.setToolTipText("Create new contact");
10 }
11
12 public void run()
13 {
14 ContactWizard wizard = new ContactWizard();
15
16 WizardDialog dialog = new WizardDialog(window.getShell(), wizard);
17 dialog.open();
18 }
19 }
|
讓我們逐步研究這段代碼:
- 無論用戶何時從菜單欄選擇 New Contact,都要執行第 12 行中的
run
方法。
- 如第 14 行所示,在向用戶顯示 GUI 向導之前需要創建
ContactWizard
類的新實例。該類設置向導的各個頁面,允許用戶向各個域提供輸入。我們稍后將更加詳細地介紹 ContactWizard
類。
- 第 16 行用兩個變量對
WizardDialog
類進行實例化:第一個變量包含了對 shell 的引用,第二個變量包含了對第 14 行中所創建的 ContactWizard
的引用。 WizardDialog
類負責為用戶顯示實際向導以及組織每個頁面的表現形式。
- 如 圖 4所示,第 17 行打開了向導對話框。
圖 4. 在 Microsoft Windows XP 上運行的 Contact 向導
實現 JFace 向導
要在地址簿應用程序中創建 ContactWizard
類,我們需要創建繼承向導基本實現的子類并覆蓋下列方法:
public void addPages()
- 該方法提供了一個掛鉤,以便在向最終用戶顯示向導之前給向導添加其它頁面。要給向導添加新的頁面,只要如 清單 3 所示的那樣調用 addPage
方法即可。在 ContactWizard
類中定義了兩個頁面。我們將在下一節中研究如何創建新的頁面。
清單 3. ContactWizard 類中的 addPages 方法
public void addPages()
{
page1 = new BasicContactPage(selection);
page2 = new AddressContactPage(selection);
addPage(page1);
addPage(page2);
}
|
public boolean performFinish()
- 當用戶點擊 Finish 按鈕時執行這個方法。在 ContactWizard
中,用這個方法收集向導的每個頁面上每個域中的數據并把它們填充到一個域對象中。請參閱 清單 4。
清單 4. ContactWizard 類中的 performFinish 方法
public boolean performFinish()
{
Contact contact = new Contact();
contact.setFamilyName(page1.getFamilyName());
contact.setGivenName(page1.getGivenName());
contact.setBusinessPhone(page1.getBusinessPhone());
contact.setHomePhone(page1.getHomePhone());
contact.setEmailAddress(page1.getEmail());
AddressBook.addContact(contact);
return true;
}
|
清單 5 顯示了具有 addPages
和 performFinish
方法的完整類。
清單 5. ContactWizard 類
...
public class ContactWizard extends Wizard
{
private BasicContactPage page1;
private AddressContactPage page2;
private ISelection selection;
public ContactWizard()
{
super();
setNeedsProgressMonitor(true);
}
public void addPages()
{
page1 = new BasicContactPage(selection);
page2 = new AddressContactPage(selection);
addPage(page1);
addPage(page2);
}
public boolean performFinish()
{
Contact contact = new Contact();
contact.setFamilyName(page1.getFamilyName());
contact.setGivenName(page1.getGivenName());
contact.setBusinessPhone(page1.getBusinessPhone());
contact.setHomePhone(page1.getHomePhone());
contact.setEmailAddress(page1.getEmail());
AddressBook.addContact(contact);
return true;
}
}
|
實現 JFace WizardPage
沒有實現 WizardPage
的類, ContactWizard
就不會有任何行為。您可以將向導看成是一堆卡片,每一張卡片都有自己的布局和設計。每個 WizardPage
負責向導中單個頁面(即卡片)的布局和行為。要創建 WizardPage
,我們需要創建繼承 WizardPage
基本實現的子類并實現 createControl
方法,從而為向導頁面創建特定的 GUI 控件。
開發 WizardPage
時,需要完成下列各項:
- 使用指定父項創建一個組合。
- 創建窗口小部件的布局。對于
BasicContactPage
類,使用 GridLayout。
- 在第 2 步創建的布局中構造并布置窗口小部件。有關 SWT 窗口小部件的更詳盡的文檔,請參閱 參考資料中的鏈接。 清單 6 演示了在
ContactWizard
類中構造和布置 BasicContactPage
所需的代碼。請參閱 圖 1中該向導頁面的抓屏。
清單 6. BasicContactPage
類中的 createControl 方法
...
public void createControl(Composite parent)
{
Compositecontainer = new Composite(parent, SWT.NULL);
GridLayoutlayout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
layout.verticalSpacing = 9;
Label label= new Label(container, SWT.NULL);
label.setText("&Given Name:");
givenNameText = new Text(container, SWT.BORDER | SWT.SINGLE);
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
givenNameText.setLayoutData(gd);
givenNameText.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
dialogChanged();
}
});
label = newLabel(container, SWT.NULL);
label.setText("&Family Name:");
familyNameText = new Text(container, SWT.BORDER | SWT.SINGLE);
gd = newGridData(GridData.FILL_HORIZONTAL);
familyNameText.setLayoutData(gd);
familyNameText.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
dialogChanged();
}
});
label = newLabel(container, SWT.NULL);
label.setText("&Nickname:");
nickNameText= new Text(container, SWT.BORDER | SWT.SINGLE);
gd = newGridData(GridData.FILL_HORIZONTAL);
nickNameText.setLayoutData(gd);
createLine(container, layout.numColumns);
label = newLabel(container, SWT.NULL);
label.setText("&Business Phone:");
businessPhoneText = new Text(container, SWT.BORDER | SWT.SINGLE);
gd = newGridData(GridData.FILL_HORIZONTAL);
businessPhoneText.setLayoutData(gd);
label = new Label(container, SWT.NULL);
label.setText("&Home Phone:");
homePhoneText = new Text(container, SWT.BORDER | SWT.SINGLE);
gd = newGridData(GridData.FILL_HORIZONTAL);
homePhoneText.setLayoutData(gd);
createLine(container, layout.numColumns);
label = newLabel(container, SWT.NULL);
label.setText("&E-Mail Address:");
emailText =new Text(container, SWT.BORDER | SWT.SINGLE);
gd = newGridData(GridData.FILL_HORIZONTAL);
emailText.setLayoutData(gd);
emailText.addModifyListener(newModifyListener()
{
public void modifyText(ModifyEvent e)
{
dialogChanged();
}
});
//dialogChanged();
setControl(container);
}
...
|
- 為任何可能需要輸入驗證或轉換的窗口小部件創建偵聽器。對于
BasicContactPage
類,創建了幾個 ModifyListeners
對特定數據域執行輸入驗證。無論何時修改文本域中的文本,都要執行 dialogChanged
方法。該方法負責處理錯誤并將錯誤報告給向導。 清單 7演示了處理輸入驗證和將任何錯誤通知向導所需的代碼。
清單 7. 處理輸入驗證類的 dialogChanged 和 updateStatus 方法
...
private void dialogChanged()
{
if (this.getGivenName().length() == 0)
{
updateStatus("Given name must be specified.");
return;
}
if (this.getFamilyName().length() == 0)
{
updateStatus("Family name must be specified.");
return;
}
if (this.getEmail().length() > 0)
{
if (this.getEmail().indexOf("@") < 0)
{
updateStatus("Enter your email address as yourname@yourdomain.com");
return;
}
}
updateStatus(null);
}
private void updateStatus(String message)
{
setErrorMessage(message);
setPageComplete(message == null);
...
|
運行地址簿應用程序
要測試和運行地址簿應用程序,請完成下列步驟:
- 在解包源代碼的目錄中運行下面這個命令:
ant run
- 執行 Ant 腳本之后,應當會出現地址簿應用程序。
- 從 File 菜單選擇 New Contact 以啟動 JFace Contact 向導。請參閱 圖 5。
圖 5. Microsoft Windows XP 上 Contact 向導的兩個頁面
結束語
通過引入 SWT/JFace 用戶界面工具箱,Eclipse 項目最終為 Java 開發人員提供了一種創建高度交互式客戶機端應用程序的方法。使用象 JFace 向導這樣的組件來研究如何用最少的代碼來創建收集用戶輸入的靈活機制,確實令人興奮。示例地址簿應用程序提供了一個構建和打包框架,您可以用該框架來創建自己的獨立 SWT/JFace 應用程序。
參考資料
關于作者 Jeff Gunther 是 Intalgent Technologies的總經理和創始人,這家公司是新興的軟件產品和解決方案供應商,其產品和解決方案采用 Java 2 企業版和 Lotus Notes/Domino 平臺。Jeff 從早期的“Mosaic”(最早的 Internet Web 瀏覽器)出現之前的時代就投身于因特網行業。他擁有軟件生命周期所有方面的專業經驗,包括 Java/J2EE、DHTML、XML/XSLT、數據庫設計和手持設備方面的特殊軟件開發專業經驗。可以通過 jeff.gunther@intalgent.com與他聯系。 |
轉自:
http://www-128.ibm.com/developerworks/cn/linux/opensource/os-ecjfw/