添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

使用 Eclipse 进行 SWT 编程

1. 为什么要使用 SWT?

SWT是IBM开发一套跨平台的GUI开发框架。为什么IBM要创建另一种GUI呢?为什么他们不使用现有的 Java GUI框架呢?要回答这些问题,我需要回到 Java 的早期时代。

Sun已经创建了一套跨平台的GUI框架 AWT (Abstract Windowing Toolkit)。 这个AWT框架使用了本地窗口组件(native widgets)不过它存在LCD问题. 这个LCD问题导致了它失去主要的平台特性。换句话说,如果平台A有窗口组件1-40而平台B有窗口组件20-25,那么这个跨平台的AWT框架只能提供这两个集合的交集。

为了解决这个问题,Sun创建了一个新的框架使用模拟窗口组件(emulated widgets)来代替本地窗口组件(native widgets)。这个方法解决了LCD问题同时提供了丰富的窗口组件,不过也产生了其他的问题。例如,Swing应用程序不再和本地程序在样子上一致。虽然JVM有了很大的改善, 但是Swing应用程序仍然存在它们本地配对物所没有的性能问题。而且,Swing应用程序消耗了太多的内存,故不适合用于PDA和移动电话等小型设备。

IBM发现这些方法都无法满足他们的需求。因此,IBM创建了新的GUI库叫做SWT,它解决了AWT和Swing框架中的问题。SWT框架使用JNI访问本地窗口组件(native widgets),如果一个窗口组件在主机平台上不能获得,那么SWT会模拟这个不能获取的窗口组件。

2. 一个 SWT 应用程序的基础材料

Display, Shell和Widgets是一个SWT应用程序的基础材料。Displays用于管理事件循环(event loops)和控制UI线程和其他线程之间的通讯。Shell是应用程序中由 操作系统 窗体管理器来管理的窗体。任何SWT应用程序都需要至少一个Display实例和1个或更多的Shell实例。

1. 不同视角看的 SWT 程序

1 说明了一个SWT应用程序的不同看法。第一幅图是简化的UI对象的继承图。第二幅图是UI对象的包含结构。第三幅图就是创建了的UI。

如果一个应用程序使用多个线程,每个线程使用自己的Display对象实例。那么你可以通过使用静态的Display.getCurent()方法得到当前活跃的Display对象实例。

一个Shell表示一个特别操作系统中的一个窗口。一个Shell可以最大化,正常化,和最小化。有两种类型的shell。一种是顶层(top-level)Shell作为Display的主窗口创建的,另一种是依赖于其他shell的对话shell。

Shell的类型是由传给Shell构造函数的style位决定的。Shell的默认值是对话Shell。也就是说,如果没有传递任何值给构造函数参数,那么创建的是默认的对话Shell。如果一个Display对象作为参数,那么它是顶层(top-level)Shell。

有些窗口组件(widget)的属性必须在创建时设定。这些窗口组件(widget)属性叫做 style bits Style bits 是在SWT类中定义的常量。如Button button = new Button( shell, <styleBits> )。当然可以通过或操作|来使用多个 style bit 。例如,要使用一个有边的按钮,你需要使用SWT.PUSH | SWT.BORDER作为style bit参数。

3. 环境设置

开发一个SWT应用程序与开发一个Swing应用程序不同。为了可以开始一个SWT应用程序的开发,你需要把SWT库加到classpath中,同时设置好对应的必要的环境变量。

第一个需要的库是swt.jar文件,它位于ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.win32_2.1.0/ws/win32目录。根据你使用的Eclipse版本,你可能需要使用不同的目录。这个swt.jar文件必须加到你的classpath中,为此到 Project->Properies->JavaBuildPath->Libraries->Add Variable -> Eclipse Home ->Extend 并按上述路径选择swt.jar库,然后单击 OK

然后,你可以编译SWT应用程序,但是由于抛出下边所示的运行时异常,无法运行它,因为swt.jar使用了本地库。你需要设置java.library.path环境变量来在Java中使用本地库。

java.lang.UnsatisfiedLinkError: no swt-win32-2133 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1403)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:832)
...
at org.eclipse.swt.widgets.Display.<init>(Display.java:287)
at Main.main(Main.java:25)
Exception in thread "main"

import org.eclipse.swt.layout.RowLayout;

import org.eclipse.swt.widgets.Display;

import org.eclipse.swt.widgets.Shell;

public class SliderExample

public static void main(String args[])

Display display = new Display();

Shell shell = new Shell(display);

shell.setLayout( new RowLayout());

// ------------------------

// Your code comes to here.

// ------------------------

shell.pack();

shell.open();

while( !shell.isDisposed())

if(!display.readAndDispatch())

display.sleep();

display.dispose();

5. Eclipse 外运行 SWT 应用程序

要在不使用Eclipse的环境下运行SWT应用程序,swt.jar库必须在classpath中,并且java.library.path环境变量必须正确设置。根据主机平台,必须有合适的本地库存在。对于Windows平台,你可以根据如下来完成本地库的配置:

  • 把swt.dll放在和程序相同的文件夹下。
  • 把swt.dll放在JAVA_HOME/bin/文件夹下。
  • 把swt.dll放在c:/windows/system32文件夹下。
  • javac -classpath c:/swt/swt.jar HelloWorld.java
    Java -classpath c:/swt/swt.jar;. -Djava.library.path=c:/swt HelloWorld
    java.library.path是JNI必需的环境变量。如果你没有设置这个环境变量。你的DLL 类是不能访问的。在这种情况下,应用程序不能正常的运行,并会抛出异常。

    6. SWT 包( Packages

    SWT主要由下列包组成。这些包的定义是从Eclipse的API文档上得到的。你可以在Eclipse的网站上获得整个API文档。
    org.eclipse.swt : 包含了定义了SWT需要使用的常量和异常的类。这个包由三个类组成:SWT, SWTException和SWTError。SWT类可能是最受欢迎的类,因为它包含了SWT库所需要的常量如键盘、错误、颜色、布局、文本样式、按钮等常量。
    org.eclipse.swt.widgets : 包含了大多数核心SWT窗口组件,包括支持的接口和类。
    org.eclipse.swt.events : 定义了SWT组件使用的typed events, listeners和events。这个包有三组不同的类:Listener接口,Adapter类和Event类。
    org.eclipse.swt.dnd : 包含了对SWT窗口组件拖放(drag-and-drop)支持的类。
    org.eclipse.swt.layout : 包含了提供对SWT窗口组件自动安置和大小控制的类。
    org.eclipse.swt.print : 包含了对SWT窗口组件提供打印支持的类。
    org.eclipse.swt.graphics : 这个包提供了实现基本绘图操作需要的点,长方形、区域,颜色,光标,字体,图像上下文(GC)等的类和包含了显示图像代码和载入/保存他们的公有API的图像类。

    7. 对话框

    对话框的实现是本地的。也就是说,对话框像窗口组件一样是平台组件。SWT的Dialogs是从Dialog抽象类继承的。对话框不是窗口组件但是他可以容纳窗口组件。

    2. Dialog类层次图.

    SWT有不同类型的对话框。有些对话框具有特殊的属性。Dialog类可以如源代码 2中使用

    MessageBox messageBox =

    new MessageBox(shell, SWT.OK|SWT.CANCEL);

    if (messageBox.open() == SWT.OK)

    System.out.println("Ok is pressed.");

    每个对话框的open()方法返回不同的类型。例如, MessageBox对话框从open()方法返回int类型。因此,需要编写不同的条件来处理每一个对话框的返回值。

    ColorDialog显示一个色彩选择调色板。它从return方法返回一个RGB对象。

    DirectoryDialog使你可以选择一个目录。它从open()方法返回一个字符串。返回值就是选择的目录。当然,也可以设置额外的过滤器来过滤有些目录。

    FontDialog使用户能够从系统所有的字体中选择一种字体。它从open()方法返回一个FontData对象。

    FileDialog使用户能够选择一个文件。另外,可以设置扩展名过滤器,路径过滤器和文件名过滤器。对话框有如表1所示的样式:

    3. MessageBox 对话框

    可用的按钮常量如下所列。使或操作可以完成不同按钮的联合。SWT框架按照style bits创建对话框。按钮常量有:SWT.ABORT, SWT.OK, SWT.CANCEL, SWT.RETRY, SWT.IGNORE,SWT.YES和SWT.NO。

    表2 显示了对话框可以使用的图标。

    8. Widgets

    SWT GUI对象是从Widget和Control类继承而来的。Widget对象是基类定义了GUI类的通用方法。Control类是所有窗口GUI类的基类也就是说从Control类继承的组件需要一个窗口或者对话框来显示。

    Menu对象也需要一个窗口来显示,但是这个需求间接得到了满足。一个Menu对象需要一个Control对象。

    4. Widget类层次图

    图 4 显示了Widget的类层次图。Widget,Item,ScrollBar和Control类是抽象类。

    8.1. Widget 事件

    Widget事件总结表 3 。简化起见,表中只包含了事件名称。我们可以很容易的使用 <EventName>Event 想出事件类的名称。同样地,使用 <Listener Name>Listener 得到相关联地Listener地名称。并不是每一事件都有相配地Adapter类。所以,有adapter地事件用粗体表明。我们可以通过 <EventName>Adaptor 来得到对应地adapter名字。
    例子:
    事件名称是Control,事件类就是ControlEvent,listener类是ControlListener,adaptor 类是ControlAdaptor。

    8.2.2 . 滑块( Slider , 标尺( Scale )和进度条( ProgressBar )窗口组件

    标尺(Scale)表示一段可选择的连续值。范围可以用Scale类的setMinimum() 和setMaximum()方法设定。并可以使用getSelection()方法得到所选择的值。标尺在一次只有一个选择的值。也就是说,没有多选的可能。

    6. 包含在一起的滑块和标尺

    根据传递给构造函数的参数值的不同,我们可以创建不同的滑块和标尺。滑块和标尺常量如表5所示:

    final Slider slider =   new Slider(shell,SWT.VERTICAL);

    slider.setMinimum(0);

    slider.setMaximum(100);

    slider.setIncrement(5);

    slider.setPageIncrement(10);

    slider.setSelection(25);

    slider.addSelectionListener(

    new SelectionAdapter()

    public void widgetSelected(SelectionEvent e)

    System.out.println("Selection:"+ slider.getSelection());

    进度条组件类似于滑块和标尺组件,但是它不能被选择。它用于显示一个任务的进度。你可以对进度条组件使用SWT.SMOOTH and SWT.INTERMINATE常量。

    8.2.3 . 文本窗口组件

    一个文本窗口组件可以用于显示或者编辑文本。另外,你可以使用StyledText窗口组件来用不同的字体和颜色显示文本。StyledText窗口组件允许设置前景、背景色和指定范围文本块的字体。

    7. Text窗口组件

    我们可以使用 6 所列的常量来创建Text窗口组件。因此,SWT.H_SCROLL和SWT.V_SCROLL常量可用于对Text窗口组件增加滚动条。

    8.2.4 . 列表( List )窗口组件

    List窗口组件可用于显示可选择的字符串列表。在选择的情况下,List对象会发送事件通告给它的listeners。这种类型的选择可以是单选,也可以是多选。选择的类型是由SWT.SINGLE和SWT.MULTI常量决定的。List窗口组件是可滚动的组件。因此SWT.H_SCROLL和SWT.V_SCROLL常量可用于给Text窗口组件增加滚动条。

    8. List 窗口组件

    下边的代码片断显示了一个简单的List窗口组件。

    List list = (List) e.getSource();

    String[] str = list.getSelection();

    for (int i = 0; i < str.length; i++)

    System.out.println("Selection: "+str[i]);

    10. Composite可以容纳其他的组合类

    组合类可以容纳其他的组合类。这种容纳关系是用一个组合窗口组件类的构造函数来建造的。与Swing相比,SWT没有add() 方法;作为代替,你必须使用构造函数来建立包容关系结构。

    正如图10中所看到的,Shell类也是一个组合类。也就是说,Shell对象,可以容纳其他的组合类。

    组合类是可以卷起的,也就是说可以使用SWT.H_SCROLL和SWT.V_SCROLL常量给组合窗口组件加上滚动条。

    8.3.1 . Table 窗口组件

    Table窗口组件可以显示一批字符串项或者图片。与其他的组合窗口组件相比,不能给table窗口组件增加组合控件。Table窗口组件的子构件必须是TableItem类型的。

    11. Table窗口组件

    表7中的常量可以用于table窗口组件

    TableItem item1 = new TableItem(table,0);

    item1.setText(new String[]{"a","b"});

    TableItem item2 = new TableItem(table,0);

    item2.setText(new String[]{"a","b"});

    table.setHeaderVisible(true);

    table.setLinesVisible(true);

    8.3.2 . Combo (组合框)窗口组件

    Combo窗口组件允许用户从值列表中选择一个值或者随意输入一个新值。组合框(combo)类似于列表组件,却使用了有限的空间。

    虽然组合框是组合性质的,但是对它增加子元素是没有意义的。它的元素必须是String类型。一元素可以使用Combo类中定义的add(String element)方法来添加到组合框中。

    12. 不同样式的组合框

    下边的SWT常量可以用于Combo窗口组件:

    8.3.3 . Tree 窗口组件

    Tree窗口组件描绘了树中项的可选择层次结构。虽然Tree类是组合的,但是不能对它增加组合类对象。Tree类的子项必须是ThreeItem类型。

    13. 不同样式的Tree窗口组件

    下表是Tree组件常量的列表。

    8.3.4 . TabFolder

    TabFolder组件允许用户从一些页面中选择一页。虽然它是组合的,但是它不能增加其他的组合窗口组件。加到TabFolder的组件必须是TabItem类型。Tab的内容可以使用TabItem的setControl(Control control) 方法来设置。

    14. TabFolder窗口组件

    一个简单的TabFolder例子:

    new Label( tabFolder, SWT.BORDER);

    label.setText( "Page " + i);

    // add a control to the TabItem

    item.setControl( label );

    8.3.5 . CoolBar 窗口组件

    CoolBar窗口组件提供了一个可以在动态摆放空间上增加项的区域。你可以增加一个或多个ToolBar组件到CoolBar上。一个CoolBar可一容纳一个或多个CoolItems。虽然是一个组合窗口组件,但是不能把其他组合类加到它上。CoolBar的子元素必须是CoolItem类型。

    15. Coolbar窗口组件

    CoolBar窗口组件使用的例子:

    new CoolItem(coolBar, SWT.NULL);

    // set the control of the coolItem

    coolItem.setControl(toolBar);

    // You have to specify the size

    Point size =

    toolBar.computeSize( SWT.DEFAULT,

    SWT.DEFAULT);

    Point coolSize =

    coolItem.computeSize (size.x, size.y);

    coolItem.setSize(coolSize);