在本系列的前三篇文章中,我介紹了用與構建 Eclipse 和獨立、功能豐富的 GUI 的 Eclipse、Eclipse Standard Widget Toolkit (SWT) 和 JFace GUI 工具包。另外還介紹了許多基本 GUI 控件、容器類型和布局管理器。隨後展示了如何把這些控件組合到一個簡單的工作應用程序中。還詳細說明了如何為這些應用程序提供一個菜單系統。最後演示了如何按照最佳實踐創建方法和類的庫,從而簡化 GUI 開發。
在這裡,我們將完成對 org.eclipse.swt.widgets 和 org.eclipse.swt.custom 包中的各種小部件的詳細觀察(除非特別說明,否則這裡討論的控件都在 widgets 包中)。關於背景知識,本文假設您至少閱讀過這個系列的 第 1 部分。
簡介
在後面幾節中,我將討論幾個 GUI 控件。這些控件通過一個叫作 BarApp 的應用程序進行演示。正如前幾部分所述,BarApp 是 BasicApplication 類(內含控件生成方法)的擴展。還使用了這個應用程序的幾幅屏幕快照來展示不同控件的特性。
圖 1 顯示了我們討論的所有控件,包括幾個 ToolBar 和一個 CoolBar。最左邊是三個有邊框的 Composite(包含一個 Label),每個 Composite 都位於一個 SashForm 面板內。而 SashForm 本身又處在一個更大的 SashForm 中有邊框的 Composite 內。靠近左側中間是一個垂直的 ToolBar,它的頂部有一個 Open Tracker 按鈕。在右上方是四個水平的 ToolBar(在兩個 CBanner 中)—— 但只能看到兩個;前兩個使用了文本標簽,後兩個使用圖片(同一張圖片)。這幾個 ToolBar 和 CBanner 全都在外圍 SashForm 中的一個 Composite 中。從清單 1 的控件層次結構中可以清楚地看出這個結構。
圖 1. BarApp 示例
清單 1. BarApp 應用程序的控件層次結構
0: BarApp {}
1: SashForm {}
2: Composite {}
3: SashForm {}
4: Composite {}
5: Label {Left Pane}
4: Composite {}
5: Label {Center Pane}
4: Composite {}
5: Label {Right Pane}
2: Composite {}
3: ToolBar {}
4: ToolItem {Open Tracker}
4: ToolItem {Check}
4: ToolItem {Drop}
4: ToolItem {}
4: ToolItem {Radio 1}
4: ToolItem {Radio 2}
4: ToolItem {Radio 3}
4: Label {}
3: CBanner {}
4: ToolBar {}
5: ToolItem {Press 1}
5: ToolItem {Check}
5: ToolItem {Drop}
5: ToolItem {}
5: ToolItem {Radio 1}
5: ToolItem {Radio 2}
5: ToolItem {Radio 3}
5: Label {}
4: ToolBar {}
5: ToolItem {Push 2}
5: ToolItem {Check}
5: ToolItem {Drop}
5: ToolItem {}
5: ToolItem {Radio 1}
5: ToolItem {Radio 2}
5: ToolItem {Radio 3}
5: Label {}
3: CBanner {}
4: ToolBar {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: Label {}
4: ToolBar {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: ToolItem {}
5: Label {}
3: CoolBar {}
4: CoolItem {Drop}
4: CoolItem {Drop}
4: CoolItem {Drop}
4: CoolItem {Drop}
4: CoolItem {Drop}
4: Button {Press Me 1}
4: Button {Press Me 2}
4: Button {Radio 1}
4: Button {Radio 2}
4: Button {Radio 3}
3: Link {<a href="http://www.somecorp.com">This is a link!</a>}
3: Composite {}
4: Button {File}
4: Button {Directory}
4: Button {Color}
4: Button {Font}
ToolBar、CoolBar 和 Tray
ToolBar 與本系列 第 2 部分 中所描述的 Menu 控件類似。ToolBar 包含 ToolItem, ToolItem 可以有文本或圖片作為按鈕。一般來說,要麼使用圖片(AKA 圖標)、要麼使用文本,不能同時使用。如果僅使用圖片,那麼 ToolItem 需要有一個 ToolTip (幫助提供信息的短語或句子),這樣當鼠標停留在 ToolItem 上時,會顯示 ToolTip,解釋圖片的功能。
ToolBar 必須定義成以下兩種完全互異的樣式之一:
HORIZONTAL —— 水平方向的
VERTICAL —— 垂直方向的
ToolBar 支持以下樣式:
FLAT —— 以平面樣式顯示項目
WRAP —— 項目換行
RIGHT —— 項目右對齊(及左對齊)
SHADOW_OUT —— 顯示陰影
ToolItem 必須定義成以下 5 種完全互異的樣式之一:
CHECK —— 可連續選擇項目(復選)。
DROP_DOWN —— 項目(通常)顯示下拉菜單。
PUSH —— 項目作為按鈕,可直接引發動作(最常見的形式)。
RADIO —— 此類項目只能選擇一個。
SEPARATOR —— 在項目組之間充當分隔符(通常是一個條),這個項目沒有功能。
以下兩個清單分別顯示了創建 ToolBar 和 ToolItem 的代碼。
清單 2. 創建 ToolBar 的方法
protected ToolBar createVToolBar(Composite parent, int style) {
return new ToolBar(parent, style | SWT.VERTICAL);
}
protected ToolBar createHToolBar(Composite parent, int style) {
return new ToolBar(parent, style | SWT.HORIZONTAL);
}
清單 3. 創建 ToolItem 的方法
protected ToolItem createToolItem(ToolBar bar, int style, String text,
Image image, String tooltip,
SelectionListener listener) {
if (image != null && (text == null && tooltip == null)) {
throw new IllegalArgumentException("image only items require a tool tip");
}
ToolItem ti = new ToolItem(bar, style);
if (image != null) {
ti.setImage(image);
}
else {
if (text != null) {
ti.setText(text);
}
}
if (tooltip != null) {
ti.setToolTipText(tooltip);
}
if (listener != null) {
ti.addSelectionListener(listener);
}
return ti;
}
多數操作系統都提供了與系統狀態關聯的特殊形式的工具欄,稱為 托盤 (Tray)。不能構造 Tray;必須使用 Display.getSystemTray() 訪問 Tray。與 ToolBar 相似,托盤中包含 TrayItem。TrayItem 沒有樣式選項,通常以 PUSH ToolItem 的形式工作。
CoolBar 類似 ToolBar,區別在於用戶可以重新安排欄中的 CoolItem,可以在 CoolItem 之間拖曳分隔條。對於欄中的 CoolItem 如何換行以及欄中項目顯示的順序,CoolBar 還允許更多控制。CoolBar 只支持 FLAT (或 NONE)樣式。CoolItem 只支持 DROP_DOWN 樣式。與 ToolItem 不同,CoolItem 有相關的控件負責實際實現項目的 GUI。如果沒有這個控件,CoolItem 就沒有功能,通常也沒有可視的實現。這個控件應當有一個 ToolTip。
下面兩個清單分別顯示了創建 CoolBar 和 CoolItem 的代碼。請注意只能創建水平 CoolBar。
清單 4. 創建 CoolBar 的方法
protected CoolBar createCoolBar(Composite parent, int style) {
return new CoolBar(parent, style);
}
清單 5. 創建 CoolItem 的方法
protected CoolItem createCoolItem(CoolBar bar, int style, String text,
Image image, SelectionListener listener) {
CoolItem ci = new CoolItem(bar, style);
if (text != null) {
ci.setText(text);
}
if (image != null) {
ci.setImage(image);
}
return ci;
}
下面這個清單顯示了如何用這個代碼創建 CoolItem 和相關控件。在這個示例中,當選中 CoolItem 的控件時,會彈出一個菜單,如圖 2 所示。請注意 CoolItem、按鈕和菜單都用 CoolBar 作為雙親。還請注意 CoolItem 的文本沒有顯示,只顯示了關聯的控件。
清單 6. CoolItem 的創建示例
CoolBar cb = createCoolBar(..., SWT.FLAT);
: // other CoolItems
CoolItem ci = createCoolItem(cb, SWT.FLAT, "Drop", null, null);
Button b = createButton(cb, SWT.PUSH, "Press Me 1", null, new SelectionAdapter() {
public void widgetSelected(SelectionEvent se) {
menu.setVisible(true);
}
});
ci.setControl(b); // associate Button with CoolItem
Menu m = new Menu(cb);
createMenuItem(m, SWT.PUSH, "Item 1", null, '1', true, null);
createMenuItem(m, SWT.PUSH, "Item 2", null, '2', true, null);
createMenuItem(m, SWT.PUSH, "Item 2", null, '3', true, null);
: // other CoolItems
圖 2. CoolItem 示例
SashForm
通常需要給應用程序 GUI 的某些部分分配可變的屏幕空間。第 3 部分 介紹了如何用 TabFolder 實現此目標。而本文將介紹使用 SashForm 的替代方法。
SashForm 顯示多個(通常是兩個)控件時,在控件間可以有分隔 Sash(框格)。可移動此框格,在控件間分隔屏幕空間。請注意在多數情況下,SashFrom 中的控件是 Composite。要獲得最佳使用性,Composite 應當有邊框,以便讓 Sash 看起來更清楚。SashForm 可以嵌套在其他 SashForm 中(看起來工作得很好),從而形成相當復雜的分隔空間的方法。SashForm 在 custom 包中。
SashForm 必須定義成以下兩種互斥的樣式之一:
HORIZONTAL —— 水平方向排列元素
VERTICAL —— 垂直方向排列元素
它們還支持 SMOOTH 樣式,在使用此樣式時,框格的移動更流暢。
以下清單顯示了創建 SashForm 的方法。
清單 7. 創建 SashForm 的方法
protected SashForm createSashForm(Composite parent, int style) {
SashForm sf = new SashForm(parent, style);
return sf;
}
protected SashForm createVSashForm(Composite parent) {
return createSashForm(parent, SWT.VERTICAL);
}
protected SashForm createHSashForm(Composite parent) {
return createSashForm(parent, SWT.HORIZONTAL);
}
圖 3 和圖 4 顯示了 SashForm 的實際效果。圖 3 展示的是外部的 SashForm 移動到右側。圖 4 則展示調整內部 SashForm 以使中央 Composite 變得更大。把這兩個圖與 圖 1 對比,可以看出 Sash 預先配置的位置是,外部 Sash 20%,內部 Sash 33%。
圖 3. SashForm 示例 1
圖 4. SashForm 示例 2
CBanner
CBanner 是帶有定制、預定義布局的特殊 Composite。它支持三個控件:Left、Right 和 Bottom,這三個控件都是可選的;通常使用的是 Left 和 Right。一般來說這些控件是 ToolBar。CBanner 在 Eclipse 中被用來使主工具區恰好位於主菜單下。CBanner 在 custom 包中。
像 SashForm 一樣,CBanner 提供了分隔器,可以容易地移動,從而分隔 Left 和 Right 控件之間分隔空間。CBanner 有一個 setSimple(boolean) 方法,控制分隔器的形式。如果為 false,分隔器就采用粗曲線形式。
以下清單顯示了創建 CBanner 的代碼。
protected CBanner createCBanner(Composite parent) {
return new CBanner(parent, SWT.NONE);
}
圖 5 顯示了一個簡單的 CBanner 和一個復雜的 CBanner。
圖 5. CBanner 示例
Link
Link 與 PUSH 按鈕類似,但是看起來更像 Web 浏覽器中的文本鏈接。Link 只支持文本內容。Link 可以使用普通文本或 HTML A 標記作為內容(通常采用 <a href="某個 url">某些文本消息</a> 的形式)。如果使用 A 標記的語法,那麼 Link 看起來就像 Web 鏈接;否則,看起來就像 Label。請注意在 Eclipse V3.1 中才可以使用 Link。
以下清單顯示了創建 Link 的代碼。
清單 8. 創建 Link 的方法
protected Link createLink(Composite parent, String text,
SelectionListener listener) {
Link l = new Link(parent, SWT.NONE);
if (text != null) {
l.setText(text);
}
if (listener != null) {
l.addSelectionListener(listener);
}
return l;
}
圖 6 顯示了一個用紅色強調的 Link。
圖 6. Link 示例
Tracker
有些時候,您可能希望在修改控件大小或移動控件的同時給用戶提供反饋。Tracker 可實現此目的。它創建一個臨時的輪廓(實際是 GUI 上的透明窗口的邊框),可以通過鍵盤或鼠標移動它或修改大小。在關閉 Tracker 時,應用程序通常就把相關控件移動或修改尺寸到與 Tracker 匹配的位置和尺寸。應用程序也可以跟著 Tracker 持續地移動控件或修改控件大小。
以下清單顯示了創建 Tracker 的代碼。
清單 9. 創建 Tracker 的方法
protected Tracker createTracker(Composite parent, int style) {
return createTracker(parent, style, null, null);
}
protected Tracker createTracker(Composite parent, int style,
ControlListener cl, KeyListener kl) {
Tracker t = new Tracker(parent, style);
if (cl != null) {
t.addControlListener(cl);
}
if (kl != null) {
t.addKeyListener(kl);
}
return t;
}
圖 7 顯示了 Check 按鈕的 Tracker,擴展到了 GUI 的右側。
圖 7. Tracker 示例
Dialog
BasicApplication 類顯示了確定退出的 MessageBox。這個 MessageBox 就是 SWT 提供的一組標准對話框的一個示例。其他一些有用的對話框是:
FileDialog —— 允許用戶選擇文件
DirectoryDialog —— 允許用戶選擇目錄
FontDialog —— 允許用戶選擇字體
ColorDialog —— 允許用戶選擇選擇顏色值
請注意 Dialog 可能不允許您對其標題文本進行設置。
下面的清單顯示了創建全部 4 種 Dialog 的代碼。
清單 10. 創建多種 Dialog 的方法
FileDialog fd = new FileDialog(getShell(), SWT.OPEN);
fd.setText("Sample File Dialog");
String path = fd.open();
DirectoryDialog dd = new DirectoryDialog(getShell(), SWT.NONE);
dd.setText("Sample Directory Dialog");
String path = dd.open();
ColorDialog cd = new ColorDialog(getShell(), SWT.NONE);
cd.setText("Sample Color Dialog");
RGB rgb = cd.open();
FontDialog fd = new FontDialog(getShell(), SWT.NONE);
fd.setText("Sample Font Dialog");
FontData d = fd.open();
圖 8 至圖 11 顯示了不同 Dialog 的實際效果。
圖 8. 文件對話框示例
圖 9. 目錄對話框示例
圖 10. 顏色選擇示例
圖 11. 字體選擇示例
結束語
本系列的第 4 部分介紹了 SWT 的控件 ToolBar、CoolBar、Tray、Link、SashForm、CBanner、Tracker 和不同的 Dialog。我們現在完成了對 SWT GUI 控件的游歷。本系列的下一篇文章將進入 JFace 的領域,介紹如何使用 JFace ContentProvider 和 LabelProvider 構建表格和樹的模型。
來源:http://www.ibm.com/developerworks/cn/opensource/os-jface4/