工具?/A>QStandard Widget ToolkitQ?A class=bluekey target=_blank>SWTQ和 JFace 库来开发用?Eclipse 环境?A class=bluekey target=_blank>囑Ş用户界面Q而且q可以将它们用于开发单独的 GUI 本机应用E序。在本文中,我将介绍一些基本的 SWTQ基?GUI 对象的名UͼcdQƈ展示如何l合使用它们?A class=bluekey target=_blank>创徏有用的应用程序?
关于 Eclipse、SWT ?JFace
正如 Eclipse ?Web 站点上所提到的,Eclipse 是一U通用工具q_。它是一?A class=bluekey target=_blank>开?/A>的、可用于M东西的可扩展 IDEQ没什么特别之处,它ؓ工具开发h员提供了灉|性以及对软g技术的控制?
Eclipse 为开发h员提供了生大量 GUI 驱动的工具和应用E序的基。而这功能的基础是 GUI ?SWT ?JFace?
SWT 是一个库Q它创徏了Java 版的本地L操作pȝ GUI 控g。它依赖于本机实现。这意味着Z SWT 的应用程序具有以下几?A class=bluekey target=_blank>关键Ҏ(gu):
它们的外观、行为和执行cM于“本机”应用程序?
所提供的窗口小部gQwidgetQ反映了L操作pȝ上提供的H口部Ӟlg和控Ӟ?
L GUI 库的MҎ(gu)行ؓ都在 SWT GUI 中得到反映?
q些目标使得 SWT 不同?Java 技术的 SwingQSwing 的设计目标是消除操作pȝ的差异?
SWT 库反映了L操作pȝ的基本窗口小部g。在许多环境下,q种Ҏ(gu)太低U。JFace 库有助于?SWT 应用E序中添加大量服务。JFace q没有隐?SWTQ它只是扩展?SWT。正如?zhn)在q一pd的后面部分中看到的,SWT 最重要的扩展之一是,应用程序的数据模型与显C及更改它的 GUI 隔离开来?BR>
在开始之前,我需要介l一?SWT 术语Q?
Widget —?基本?SWT GUI lgQ类g Java AWT 中的 Component ?Swing 中的 JComponentQ。Widget 是一?A class=bluekey target=_blank>抽象c?/A>?
Control —?拥有操作pȝ的对{物的窗口小部gQ换句话_在操作系l中h同一w䆾Q。Control 是一个抽象类?
Composite —?包含其他控g的控ӞcM?Java AWT 中的 Container ?Swing 中的 JPanelQ?
Item —?其他控g包含的窗口小部gQ该控g可能不是复合控gQ,比如列表和表。注意,包含一些项的控件很包含其他控Ӟ反之亦然。Item 是一个抽象类?
q些H口部件被安排在承层?A class=bluekey target=_blank>l构中。参见图 1、图 2 和图 3Q了解它们是如何安排的。在?2 中,Basic1 cL来自本文的类Q而其他所有类都是标准?SWT H口部件?
?1. SWT Widget ?/B>
?2. SWT Composite ?/B>
?3. SWT Item 列表
注意QEclipse h跨^台特性(因此可以在许多操作^Cq行Q,本文Z Eclipse ?Microsoft? Windows? 版本。因此,本文包含的每个例子都应该能够不加M更改地在其他q_上用。还要注意的是,本文是基?Eclipse V3.0 的。Eclipse V3.1 中添加了许 GUI H口部件类型和Ҏ(gu)?
基本控g
几乎所?SWT GUI 都是从某些基部分开始创建的。所?SWT H口部仉可以?org.eclipse.swt.widget
?org.eclipse.swt.custom
包中扑ֈ。(一?Eclipse 插gq在其他包中提供了定制的H口部件。)H口部件包中包含一些基于操作系l控件的控gQ而定制包中则包含一些超出操作系l控仉之外的控件。一些定制的软g包控件类gH口部件包中的控g。ؓ了避免命名冲H,定制控g的名U都是以“C”开始的Q例如,比较 CLabel ?LabelQ?
?SWT 中,所有控Ӟ除了一些高U控Ӟ比如 shellQ将在后面进行讨论)在创建的时候都必须有一个父控gQ一个复合实例)。在创徏的时候,q些控g被自动“添加”到父控件中Q这与必L添加到父控件中?AWT/Swing 中的控g有所不同Q自动添加生了一U“自上而下”地构?GUI 的方法。这P所有控仉可以采用一个复合父控gQ或者一个子c)作ؓ构造函数的参数?BR>
大多数控仉有一些必d创徏时设|的标记选项。因此,大多数控件还有另外一个构造函数参敎ͼ我们通常UC为样式,该参数提供了讄q些选项的标记。所有这些参数值都?static final int
Qƈ且都是在 org.eclipse.swt
包的 SWT
cM定义的。如果不需要Q何参敎ͼ则可以?SWT.NONE
倹{?
标签
标签可能是最单的控gQ标{?被用于显C纯文本Q没有颜艌Ӏ特D字体或样式的文本)或称为图标的图像。标{不接受焦点Q换句话_用户不能通过 Tab 键或鼠标Ud到标{)Q因此,标签无法产生输入事g?BR>
清单 1 展示了如何创Z个简单的文本标签?BR>
清单 1. 创徏一个带文本的标{?/B>
import org.eclipse.swt.widget.*;
:
Composite parent = ...;
:
// create a center aligned label
Label label = new Label(parent, SWT.CENTER);
label.setText("This is the label text");
|
注意Q该文本是采用不同于构造函数的单独的方法设|的。这是所?SWT 控g的一个典型象征。只有父控g和样式是在构造函C讄的,其他所有属性都是在已创建的对象上设|的?
׃q_的限Ӟ标准标签控g不能同时拥有文本和图标。ؓ了支持同时拥有文本和图标Q可以?CLabel 控gQ如清单 2 中所C?BR>
清单 2. 创徏一个包含文本和囑փ的标{?/B>
import com.eclipse.swt.graphics.*;
import org.eclipse.swt.widget.*;
import org.eclipse.swt.custom.*;
:
Composite parent = ...;
Image image = ...;
:
// create a left aligned label with an icon
CLabel Clabel = new CLabel(parent, SWT.LEFT);
label.setText("This is the imaged label text"");
label.setImage(image);
|
文本
在标{显C文本的同时Q?zhn)时常q想允许用户插入文本。文?控g是用于此目的的。文本可以是单行的(一个文本字D)Q也可以是多行的Q一个文本区域)。文本还可以是只ȝ。文本字D中没有描述Q因此,常常通过标签控g处理它们Q以定它们的用途。文本控件还可以包含一个“工hC”,提供关于控g用途的信息Q所有控仉支持q一Ҏ(gu))?
清单 3 昄了如何用允怋用的有限数量的特性来创徏一个简单的文本字段。选择默认文本是ؓ了便于擦除。
清单 3. 创徏一个包含选定的默认文本和一个限制条件的文本
import org.eclipse.swt.widget.*;
:
Composite parent = ...;
:
// create a text field
Text name = new Text(parent, SWT.SINGLE);
name.setText("<none>");
name.setTextLimit(50);
name.setToolTipText("Enter your name -- Last, First");
name.selectAll(); // enable fast erase
|
按钮
通常Q?zhn)希望用户指出应该何时q行某项操作。最常见的做法是使用按钮 控g。存在以下几U样式的按钮Q?
- ARROW —?昄Z个指向上、下、左、右方向的箭头?
- CHECK —?已标记的复选标记?
- FLAT —?没有凸v外观的按钮?
- PUSH —?瞬时按钮Q最常见的事件源Q?
- RADIO —?h排他性的_性标讎ͼsticky markQ,其他所有单选按钮都在相同的l中?
- TOGGLE —?一个粘性按钮?
清单 4 创徏了一个“Clear”按钮:
清单 4. 创徏一个按?/B>
import org.eclipse.swt.widget.*;
:
Composite parent = ...;
:
// create a push button
Button clear = new Button(parent, SWT.PUSH);
clear.setText("Clea&r");
|
名称中的 &
D利用紧接着的一个字母创Z个加速器Q允?dng)R过 Ctrl+<字母> 序的方式按下按钮(控g序׃机操作系l决定)?
事g监听?/B>
通常Q?zhn)可能惛_选择按钮Q特别是某种推式按钮Q的时候执行一些操作。?zhn)可以通过向该按钮d一?SelectionListener
Q在 org.eclipse.swt.events
包中Q做到这一炏V当按钮状态发生改变时Q通常是按钮被按下Q,׃生成事g。清?5 在单?Clear 按钮时输Z条消息。
清单 5. 按钮事g处理E序
import org.eclipse.swt.events.*;
:
// Clear button pressed event handler
clear.addSelectionListener(new SelectionListener() {
public void widgetelected(selectionEvent e) {
System.out.println("Clear pressed!");
}
public void widgetDefaultSelected(selectionEvent e) {
widgetelected(e);
}
});
|
此代码用了一个匿名的内部c,但?zhn)q可以用指定的内部cL单独的类作ؓ监听器。多数包含两个或更多Ҏ(gu)?...Listener
c还有一个类似的 ...Adapter
c,q个cL供了一些空的方法实玎ͼq且可以减少(zhn)需要编写的代码数量。例如,q有一?SelectionAdapter
c,q个cdC SelectionListener
?
注意Q在q些Ҏ(gu)中执行的操作必须快速完成(通常不一U时_Q或者说 GUI 的反应将是迟钝的。更长时间的操作Q比如访问文Ӟ需要单独的U程Q但那是以后某期文章的主题?
复合控g
xQ我们已l讨Z一些单独的控g。在多数 GUI 中,许多控g被组合在一起以提供丰富的用户体验。在 SWT 中,q种l合是通过 Composite cd现的?
复合控g可以在Q何别上q行嵌套Qƈ且可以合和匚w控gQ将它们作ؓ子控件进行组合。这样做可以极大地减?GUI 开发的复杂性,qؓ GUI 代码重用Q通过装内部 GUIQ创造了Z。复合控件可以是有边界的Qƈ且这些边界很Ҏ(gu)在视觉上产生hQ或者它们也可以是无边界的,无缝集成到更大的l中?
清单 6. 创徏一个有边界的复合控件?BR>
?6. 创徏一个有边界的复合控?/B>
import org.eclipse.swt.widget.*;
:
Composite parent = ...;
:
Composite border = new Composite(parent, SWT.BORDER);
|
除了边界之外QGroup 复合子类q支持标题。在定义排他性按钮集合时Q组通常被用来包含单选类型的按钮?
清单 7 创徏了一个有边界的组?BR>
清单 7. 创徏一个有边界的组
import org.eclipse.swt.widget.*;
:
Composite parent = ...;
:
Group border = new Group(parent, SWT.SHADOW_OUT);
border.setText("Group Description");
|
shell
shell 是一U可能没有父复合控g的复合控Ӟ框架或窗口)Q此外,它还有一个作为父控g?DisplayQ这通常也是默认讄。shell 有很多种样式Q但最常见的样式是 SWT.SHELL_TRIM
?SWT.DIALOG_TRIM
。shell 可以是模态的Q也可以是非模态的。模?shell 常常用于对话框,防止?GUIQ如果有的话Q在关闭?shell 之前被处理?
清单 8 创徏了一个框架样式的非模?shell?BR>
清单 8. 创徏一个顶U?shell
import org.eclipse.swt.widget.*;
:
Shell frame = new Shell(SWT.SHELL_TRIM);
:
|
shell 可以有子 shell。这些子 shell 是与?shell 相关的独立桌面窗口(也就是说Q如果父 shell 关闭Q那么其所有子 shell 也将关闭Q?
清单 9 创徏了一个对话框样式的子 shell?BR>
清单 9. 创徏一个对话框 shell
:
Shell dialog = new Shell(frame, SWT.DIALOG_TRIM);
:
|
参见?4 中具?SWT.SHELL_TRIMSee ?shellQ以及图 5 中具?SWT.DIALOG_TRIM ?shellQ了解这些值如何媄?shell 的整z性?
?4. h SWT.SHELL_TRIM ?shell

?5. h SWT.DIALOG_TRIM ?shell

布局理?/STRONG>
复合控g常常包含多个控g。可以用以下两U方法安排这些控Ӟ
- l对定位 —?为每个控件设|明的 X ?Y 位置Qƈ通过代码讄一定的宽度和高度?
- 托管定位 —?每个控g?X、Y、宽度和高度都是通过LayoutManager 讄的?
在多数情况下Q应该选择使用 LayoutManagersQ因为很Ҏ(gu)调整它们来适应可变大小?GUI。SWT 也提供了一些布局理器供(zhn)用;在这一期的pd文章中,我们讨ZU基本的布局理器:FillLayout ?GridLayout。在q两U情况下Q每当重新设|复合控件的大小Q都需要进行定位?
一些布局理器常常是专ؓ某一个复合控件分配的。一些布局理器只使用它们自n的参数就可以控制Q而另一些布局理器还需要其他参?—?LayoutDataQ该参数是在它们理的复合控件中的每个控件上指定的?
FillLayout
FillLayout 以行或列的Ş式安排控件。每个控件所讄的大将与填充该复合控g所需的宽度和高度相同Q在q些控g之间Q空间是q_分配的。一U特D情冉|Q在仅有一个子控gӞ该控件的大小被设|ؓ填充整个父复合控件的大小?BR>
清单 10. 使用 FillLayout 创徏一列控?/B>
import org.eclipse.swt.widget.*;
import org.eclipse.swt.layouts.*;
:
Composite composite = ...;
FillLayout fillLayout = new FillLayout(SWT.VERTICAL);
composite.setLayout(fillLayout);
|
GridLayout
GridLayout 提供了一个功能更强大的布局Ҏ(gu)Q该Ҏ(gu)cM于?HTML 表的Ҏ(gu)。它创徏?2-D |格的单元格。可以将控g攄在一个或多个单元gQ可以称之ؓ单元D)。单元格的大可以是相等的,或者是|格宽度或高度的某个l定可变癑ֈ比。可以将控gd到某一行的下一个可用列中,如果q一行中没有更多的列Q那么该控g移动到下一行的W一列中?
清单 11 创徏了一个复合控Ӟ该控件有两行和两个列Q其中包含两个已标记的文本字Dc这些列可以有不同的宽度?BR>
清单 11. 创徏一个控件表
import org.eclipse.swt.widget.*;
import org.eclipse.swt.layouts.*;
:
Composite composite = ...;
GridLayout gridLayout = new GridLayout(2, false);
composite.setLayout(gridLayout);
Label l1 = new Label(composite, SWT.LEFT);
l1.settext("First Name: ");
Text first = new Text(composite, SWT.SINGLE);
Label l1 = new Label(composite, SWT.LEFT);
l2.setText("Last Name: ");
Text last = new Text(composite, SWT.SINGLE);
|
GridData
考虑一下这U情况:(zhn)需要指定每个控件如何用其单元g的剩余空间。ؓ了给每个单元格提供这U精控Ӟd?GridLayout 的托复合控件的控g可以拥有 GridData 实例QLayoutData 的子c)?
清单 12 讄了这些文本字D,以便采用所有可用的剩余I间Q根据前面的清单Q?BR>
清单 12. 配置一个扩展到所有可用空间的布局
first.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
last.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
构徏一个运行程?/STRONG>
现在是时候来看一下我们已l在单的可执行例?Basic1 中讨的所?SWT 控g了。请参阅 参考资料,以获得该应用E序的完整源代码?BR>
SWT GUI 需要一个已配置好的环境来运行。这个环境是通过一个显C实例提供的Q该实例提供了对L操作pȝ昄讑֤的访问。这个显C实例允许?zhn)处理每个用户输入Q鼠标或键盘Q来处理(zhn)的 GUI?
清单 13 创徏了一个环境和一?GUIQƈ昄了这?GUI?BR>
清单 13. 创徏一?GUI 应用E序q启动它
import org.eclipse.swt.widget.*;
:
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Shell Title");
// *** construct Shell children here ***
shell.open(); // open shell for user access
// process all user input events
while(!shell.isDisposed()) {
// process the next event, wait when none available
if(!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose(); // must always clean up
|
此代码创Z一个类g?6 的窗口?
?6. CZ应用E序

l束?/B>
?SWT ?JFace pd的第一期中Q我们介l了大多数基?SWT H口部件控Ӟ标签、文本、按钮、复合控件和 shell。这些控Ӟ与显C类Qdisplay classQ相l合Q允许创建全功能?GUI?

]]>