Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > Java > SWT/JFace开发入门指南
【标  题】:SWT/JFace开发入门指南
【关键字】:SWT/JFace
【来  源】:http://blog.csdn.net/lly520/archive/2006/10/16/1336373.aspx

SWT/JFace开发入门指南

Your Ad Here
写在前面的话
终于决定提起笔来写一篇关于swt和JFace编程的文章。在开始之前,我想先介绍一下你能够从将要出现的这一系列文章里得到什么,以及更重要的,你不能得到什么。我们的时间是如此之重要,以至于我们很难容忍把它浪费在自己不关心的事情上。
因为我刚开始写,所以到底这些文章会分成几次发布出来,也很难讲。但是我心里大体有这样一个提纲。也就是说,我打算介绍以下方面的内容:
l         设定swt以及JFace的开发环境
l         swt的一些简单部件(widget)介绍
l         JFace的一些入门性介绍
l         swt和JFace的事件模式
l         通过一些简单的例子说明如何利用swt和JFace编写图形化应用程序
我还要说明一下你不能从本文中得到的信息,这些信息包括:
l         swt和JFace相关内容非常深入的介绍:正如你从题目中了解到的,本文的定位是“入门”,也就是说假定的读者是那些对swt和JFace开发没有什么了解的人。所以我并不打算进行一个深入的介绍。因为我相信在入门之后,他们能够找到更好的资料(此外,我可能会写另外一个系列文章来介绍)。
l         eclipse的使用:我假定你在读这篇文章的时候已经对eclipse有所了解,所以不会解释到具体eclipse如何使用。
l         eclipse插件开发:虽然eclipse插件开发和本文内容有着千丝万缕的联系,我决定还是不把它列为介绍的内容。这方面,你仍然可以找到相当多的资料供参考。
与作者联系
如果你希望和我联系的话,你可以发email到jayliu@mail.csdn.net
延伸阅读
你不知道什么是eclipse么?你可以打开http://www.eclipse.org,这是eclipse的官方站点。
如果你希望对eclipse功能有详细的了解,你可以读一下这本书《CONTRIBUTING TO ECLIPSE》。
你不知道什么是swt/JFace么?你可以看一下Wikipedia中的介绍:http://en.wikipedia.org/wiki/Swt

http://en.wikipedia.org/wiki/Eclipse_%28computing%29

你对eclipse,swt的历史感兴趣么?我强烈推荐你看一下这篇八卦:http://www.csdn.net/news/newstopic/20/20433.shtml
如果你对eclipse的一些新闻比较感兴趣的话,可以关注一下大胃的blog: http://www.blogjava.net/sean/
最后你可以从一个地方得到所有你想要的东西:http://www.google.com
OK,介绍到此为止,下面我开始正文:
Hello,world!:搭建一个swt/JFace开发环境
在前面我曾经提到过:我们假定你对eclipse开发有一些了解。所以在这一节中,我将示范如何搭建一个swt/JFace开发环境,并且用一个老掉牙的Hello,world!程序作为示范。
建立开发环境
你完全可以不使用eclipse,而是使用别的IDE来进行开发,但是你需要有swt/JFace的一些库文件。
为了能够进行正常的swt/JFace开发,你需要做以下工作:
第一步:建立一个Java工程:因为这个是大家都非常熟悉的,所以就不再赘述,你可以建立一个任何名字的Java工程。
第二步:导入swt以及JFace的库文件。这也就意味着:将swt/JFace相关的库文件导入到工程的classpath中去。
需要的库文件有哪些呢?打开eclipse安装目录下的plugins文件夹,我们需要找到以下jar文件:
l         org.eclipse.swt_3.x.x.jar
l         org.eclipse.jface_3.x.x.jar
l         org.eclipse.core.runtime_3.x.x.jar
l         org.eclipse.ui.workbench_3.x.x.jar

 

这就是我们搭建一个基本swt/JFace 程序所需要基本的一些库文件了。其中3.x.x视你所使用的eclipse版本而定,譬如我的eclipse版本是3.1M6,这些3.x.x就是3.1.0。将他们加入你程序的classpath中。
为了更加清楚地说明如何做,你可以看一下下面的图1。这是我在eclipse的做法:打开工程的properties对话框,然后选择Java Build Path中的Libraries选项卡,将这些jar导入进来。当然你可以有自己的做法。
设定classpath
1
第三步:为你的java程序添加本地库文件。如果你使用windows的话,你可能注意到在eclipse的plugins目录下还有一个org.eclipse.swt.win32_3.x.x.jar,将这个jar解压以后在os/win32/x86目录下有几个dll文件。这几个dll为swt通过JNI访问windows本地API提供了接口,我们需要将使java程序在启动时候即能够访问它。你可以有多种办法实现这个目的:
最简单的办法就是直接把这几个文件拷贝到你jre的bin目录下
你也可以设定环境变量时候,在PATH中加入这几个dll文件的目录。
你还可以在运行程序时候指定java.library.path为这几个dll所在的目录,在eclipse中,如果你打开Help菜单中About eclipse Platform,然后在出现的对话框中选择configuration details按钮,你可以在接下来出现的对话框中找到java.library.path
配置java.library.path你还有另外一种办法,就是在最后运行程序的时候,从Run菜单中选择Run As..而不是Run As java Application,填写好必要的其他参数以后打开Argument选项卡,然后在VM Argument输入框中填写该参数为dll文件的路径,如图2所示
vm参数设定
2
通过这三步工作,你就可以编写swt/JFace程序了。

  
 
Hello,World!
下面的内容就是我们Hello,world!的示例。首先建立一个类,我将这个类取名为HelloSwt,在我的工程中,它位于swtjfacesample包的下面。类的内容如下:
 1package swtjfacesample;
 2
 3import org.eclipse.swt.SWT;
 4import org.eclipse.swt.widgets.Display;
 5import org.eclipse.swt.widgets.Shell;
 6import org.eclipse.swt.widgets.Text;
 7
 8public class HelloSwt {
 9    /**
10     * Hello,world!
11     * 
12     * @param args
13     */

14       public static void main(String[] args) {
15        Display display = new Display();
16        Shell shell = new Shell(display);
17        
18        Text helloText = new Text(shell, SWT.CENTER);
19        helloText.setText("Hello,World!");
20        helloText.pack();
21        
22        shell.pack();
23        shell.open();
24
25        while (!shell.isDisposed()) {
26            if (!display.readAndDispatch()) {
27                display.sleep();
28            }

29        }

30        display.dispose();
31
32    }

33}

34

代码段1

关于这段代码的内容,我们会在下面的内容中进行详细介绍。现在我们可以尝试着运行一下,确定已经编译完成后从eclipsePackage Explorer中选中这个类然后点右键,在弹出的菜单中你会看到Run As,进一步选中这一项,然后在二级菜单中选“Run As java Application”,如果运行正常的话你会看到如图3的运行结果:
Hello,World!

Q&A:出现了问题怎么办

Q:我的程序编译时候出现了错误!

A:如果是提示诸如Text,Display这些类不能够被成功引入,那么你需要检查一下是否我们前面提到的jar都已经被成功引入到你的classpath

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Q:编译成功了但是不能运行,出现了异常

A:检查一下异常信息,如果你的异常信息类似这样:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no swt-win32-3128 in java.library.path

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

的话,那说明我们在前面第三步提到的那些dll没有正常工作,最好能够按照前面的说明重新配置一下。

 

 

 

 

 

 

 

 
从Hello, world!开始了解Display和Shell

在这一节中,我们从前面所列举出来的Hello, world!程序开始对swt进行一些初步的探索。所谓的初步是指,我们会介绍编写swt程序的基本思路,以及对两个重要的类:Display和Shell作一些介绍。

因为这一节和前一节是分成两个部分贴出来的,所以我仍然将Hello, world!的代码段在下面列出来:

 1package swtjfacesample;
 2
 3import org.eclipse.swt.SWT;
 4import org.eclipse.swt.widgets.Display;
 5import org.eclipse.swt.widgets.Shell;
 6import org.eclipse.swt.widgets.Text;
 7
 8public class HelloSwt {
 9    /**
10     * Hello,world!
11     * 
12     * @param args
13     */

14       public static void main(String[] args) {
15        Display display = new Display();
16        Shell shell = new Shell(display);
17        
18        Text helloText = new Text(shell, SWT.CENTER);
19        helloText.setText("Hello,World!");
20        helloText.pack();
21        
22        shell.pack();
23        shell.open();
24
25        while (!shell.isDisposed()) {
26            if (!display.readAndDispatch()) {
27                display.sleep();
28            }

29        }

30        display.dispose();
31
32    }

33}


代码段 2

这段程序虽然很简单,但是它反映了我们书写swt程序的步骤,这些步骤是:

1.      创建一个Display对象

2.      创建一个或者多个Shell对象,你可以认为Shell代表了程序的窗口。

3.      在Shell内创建各种部件(widget)

4.      对各个部件进行初始化(外观,状态等),同时为各种部件的事件创建监听器(listener)

5.      调用Shell对象的open()方法以显示窗体

6.      各种事件进行监听并处理,直到程序发出退出消息

7.      调用Display对象的dispose()方法以结束程序。

 
 

在Hello,world!程序中,为了让程序更加简单,我们没有创建事件监听器,在以后的内容中会进行专门介绍。

现在让我们稍微深入一些,看一下这些Display,Shell有什么作用以至于我们每个程序都必须有它们存在。

Display:与操作系统沟通的桥梁

我们在前面说过,每个swt程序在最开始都必须创建一个Display对象。Display对象起什么作用呢?它是swt与操作系统沟通的一座桥梁。它负责swt和操作系统之间的通信。它将swt/JFace的各种调用转化为系统的底层调用,控制操作系统为swt分配的资源。同时我们也可以通过Display对象得到操作系统的一些信息。

Display是一个“幕后工作者”,它为swt/JFace提供支持,但是你并不能够从某个用户界面中看到它的影子。

在前面的Hello,world!程序中,我们可以看到构建一个Display对象是和普通的Java对象一样通过构造函数实现的。它为实现图形界面准备了最基本的条件。而在程序结束时我们必须显式地调用dispose() 方法来释放程序运行中所获得的资源。一般来说,一个程序只需要一个Display对象,当然没有人禁止你创建多个Display对象。但是在swt的javadoc中,我们可以看到关于这个问题一些描述:

“Applications which are built with SWT will almost always require only a single display. In particular, some platforms which SWT supports will not allow more than one active display. In other words, some platforms do not support creating a new display if one already exists that has not been sent the dispose() message.”

Display有着众多的方法,我们不可能一一介绍。在这里只挑选几个可能会比较常用的作一些简单介绍。

l         setData()和getData():这一对函数允许我们为Display对象设定一些数据,setData()的参数中key和value类似于我们在使用Map对象中key和value的含义。

l         getShells()得到关联到该Display对象的所有没有dispose的Shell对象

l         getCurrent()得到与用户交互的当前线程

l         readAndDispatch()得到事件并且调用对应的监听器进行处理

l         sleep()等待事件发生

Shell:窗口

一个Shell对象就是一个窗口。你可以在上面放置各种部件创建丰富的图形界面。

我们都知道窗口有很多种,比如窗口有可以调整大小的,有不可以的,有的没有最大化最小化按钮。这些窗体的特征在swt中被成为风格(style)。一个窗体的风格可以用一个整数进行定义。这些风格的定义在org.eclipse.swt.SWT中。

Shell对象可用的风格包括:BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE , PLICATION_MODAL, MODELESS, PRIMARY_MODAL,S YSTEM_MODAL

这些风格我们不作一一介绍,你可以从他们字面意义看出一些含义来,当然也可以参考对应的javadoc。

我们可以在一个Shell的构造函数中定义它的风格,比如在前面的Hello,world!程序中,我们可以这样定义Shell。 
Shell shell = new Shell(display,SWT.CLOSE | SWT.SYSTEM_MODAL);
  

最后得到的窗体没有最大化和最小化按钮,并且大小是固定不变的。

因为swt运行于各种平台之上,而这些平台上的窗口管理器千差万别,所以所有这些风格都不是肯定可以实现的。在swt的javadoc中,这被称为暗示(hints)。

Shell对象的方法大都和GUI有关,比如setEnabled()设定了窗体是否能够和用户进行交互,setVisble()设定了窗体是否可见,setActive()将窗体设为当前的活动窗口。

我们可以用open()方法打开一个窗体,close()方法关闭一个窗体。

小结

本节讨论了Display和Shell的一些概念,这是我们以后进一步了解swt的基础。在下一节中,我将介绍各种部件(widget)的用法,所谓部件,是指文本框,标签等UI实体。

初步体验widget

大家好,五一已经过去了,你们玩得开心么?

在前面的两篇文章中,我向大家介绍了swt的一些基本知识,现在让我们继续下去讨论一下swt中的widget相关的一些知识以及介绍几种最为简单的widget。

从Widget和Control开始

Widget是Control的父类,而Control是我们使用的大多数部件的父类。我们在以前的一些编程语言中可能接触过“控件”或者“组件”之类的概念,部件(widget)的概念大体和这些相当。

在org.eclipse.swt.widgets中定义了众多的widget,甚至我们前面介绍的Shell也被当成widget的一种。

因为可用的widget如此之多,所以我大概没有办法全部一一介绍。在这一节中,我会介绍几种常用的widget。相信善于触类旁通的你通过这些极为简略的介绍应该可以开始使用各种widget,在使用中不断完善自己的认识。

首先我们来介绍Widget。它是一个抽象类,也是所有widget的父类。通过介绍这个类,我们可以得出这所有widget的一些共有特性。

Widget的方法中dispose()方法我们在以前曾经见到过,调用这个方法时候,所谓的接收者(receiver,譬如我们这样写:awidget.dispose(),那么awidget就是接收者,而这句话所处的对象成为调用者或者caller)和接收者中所包含的其他widget会释放它们所占用底层操作系统的资源。这也就是说你不必显式地为程序中创建的每个widget进行dispose()调用,而只需要确保最外层的widget(比如Display)进行了dispose()就可以了。

另外还可以通过isDisposed()判断是否该widget(接收者)已经进行了dispose。

Widget中的getStyle()方法得到widget的风格,而getDisplay()得到所处的Display对象。

此外Widget中还有两个重要方法getData()和setData(),这两个方法允许我们为一个widget附加其他的信息。特别是在你需要跨模块传递widget的时候,这个功能显得非常有用。比如如果一个文本框中显示了一段文章中的某句话,如果我们同时希望把这整篇文章的题目和作者附加上的话可以这样写: 
1atext.setData("title","I Have A Dream");
2atext.setData("author","Martin Luther King");


代码段 3

在程序的其他部分可以用atext.getData(“title”)得到这篇文章的题目,或者用atext.getData("author")得到作者。

在前面我们提到过,Control是今后我们所使用大部分widget的父类。在这里我不单独进行介绍,而是在后面的部分中介绍。

创建部件

和创建其他java object一样,我们通过使用new操作符创建部件的实例。有一点比较特殊的可能你需要使用带参数的构造函数进行new操作。类似下面的程序:

Text text=new Text(shell,SWT.CENTER);

这种方法适用于几乎所有的widget,其中第一个参数是父widget,也就是指明了该widget需要被放置道另外哪一个widget之中,而第二个参数是这个widget的风格。

大小和位置

仅仅创建一个部件并不足以让你看到它,因为一个部件初始的长和宽都是0。你还需要设定它的大小。你可以用setSize()或者setBounds()方法手动设定部件的大小,也可以让系统自动调整部件的大小到一个合适的值,这个值也被成为首选尺寸(preferred size)。

可以通过调用pack()方法让系统调整控件大小。如果你希望系统自动调整,那么你需要首先设定控件需要表达的内容。举个例子来说,如果你的部件是一个文本框或者标签,你应该首先设定它所要显示的文本,这样系统可以通过文本的长度计算。

对于部件的位置,同样可以使用setLocation()或者setBounds()进行设定。

这里值得一提的是所谓的bounds,其实bounds可以看成是大小和尺寸的综合。比如setBounds(int x, int y,int width,int height)的参数中,x和y描述的是位置信息,而width和height描述了大小。

隐藏与失效

通过部件的setVisible方法可以控制部件进行隐藏或是显示。通过setEnabled方法可以控制部件是否有效。一个无效的部件不会对用户的任何动作作出响应。这两个方法的参数都是布尔型的。

提示文本

可以通过setToolTipText()方法设定部件的提示文本。

几种常用的部件
Label

标签用来显示静态的文本或者图像。关于图像和色彩我会在后面的部分进行介绍。

标签可以使用SWT.CENTER, SWT.LEFT, SWT.RIGHT中的一种指明文本的对齐方式(居中对齐,左对齐,右对齐)。

你也可以通过设置标签属性为SWT. SEPARATOR 使标签成为一条分隔符。

下面这个程序给出了标签的两种表现形式,其中使用了Layout,关于Layout的详细情况也会在后面的部分进行介绍:

 

 1public class Labels {
 2  
 3    public static void main(String[] args) {
 4        Display display = new Display();
 5        Shell shell = new Shell(display,SWT.SHELL_TRIM);
 6        RowLayout layout=new RowLayout(SWT.VERTICAL);
 7        shell.setLayout(layout);
 8        shell.setText("Labels");
 9        Label label1=new Label(shell,SWT.CENTER);
10        label1.setText("Label Demo");
11        Label label2=new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL);
12        shell.setSize(100,100);
13        shell.open();
14
15        while (!shell.isDisposed()) {
16            if (!display.readAndDispatch()) {
17                display.sleep();
18            }

19        }

20        display.dispose();
21    }

22}

23

 


代码段 4

最后得到的效果可以参照下图:

 

o_labels.JPG
4

Text

Text就是最简单的文本框,与标签一样,我们可以通过设定它的风格来表示它的对齐方式(SWT.CENTER,SWT.LEFT,SWT.RIGHT),另外还有其他一些用于文本支持的方法,比如insert(),paster(),copy(),setSelection(),selectAll()等,这些方法在后面介绍swt事件模式会进行更详细的介绍。

Button

在swt中,Button并不仅仅是按钮。构造时候定义的风格不同,所体现出的外观也不一样。

如果风格定义成SWT.PUSH,它就是一个普通的按钮。

如果定义为SWT.TOGGLE,它在被按下以后会保持按下的形状(而不会弹起来),直到鼠标再次在上面按一下才会回复弹起的形状。

如果风格定义为SWT.ARROW,它是一个带箭头的按钮,箭头的指向可以选择SWT.LEFT,SWT.RIGHT,SWT.UP,SWT.DOWN中的一个。

如果定义为SWT.CHECK,它是一个复选框。

如果定义为SWT.RADIO,它是一个单选框。

下面一段程序演示了各种不同的Button。

 1public class Buttons {
 2
 3        public static void main(String[] args) {
 4            Display display = new Display();
 5            Shell shell = new Shell(display,SWT.SHELL_TRIM);
 6            RowLayout layout=new RowLayout(SWT.VERTICAL);
 7            shell.setLayout(layout);
 8            shell.setText("Buttons");
 9            
10            Button pushbutton=new Button(shell,SWT.PUSH | SWT.CENTER);
11            pushbutton.setText("SWT.PUSH");
12
13            Button togglebutton=new Button(shell,SWT.TOGGLE | SWT.LEFT);
14            togglebutton.setText("SWT.TOGGLE");
15            togglebutton.setSelection(true);
16            
17            Button arrowbutton=new Button(shell,SWT.ARROW | SWT.LEFT);
18            
19            
20            Button checkbox=new Button(shell,SWT.CHECK);
21            checkbox.setText("SWT.CHECK");
22          
23            Button radio=new Button(shell,SWT.RADIO);
24            radio.setText("SWT.RADIO");
25            radio.setSelection(true);
26            
27            shell.pack();
28            shell.open();
29
30            while (!shell.isDisposed()) {
31                if (!display.readAndDispatch()) {
32                    display.sleep();
33                }

34            }

35            display.dispose();    
36    }

37}


代码段 5

最后得到的窗口如下图:

 

o_buttons.JPG
5

小结

在这一节中我向大家介绍了widget的一些基本知识,还有几种简单的widget。你可能注意到这些描述仅仅限于外观方面,如何让widget和用户交互起来呢?这需要我们处理各种用户事件,在下一节中我会向大家介绍swt的事件模式。

让你的swt程序动起来

在向使用者提供最差的用户体验方面,中国的IT企业始终走在时代的最前端。之所以有这样的感慨其实是来源于往blog上贴上一节的内容:我用了一整天的功夫,不断与CSDN各种莫名其妙的出错提示进行斗争,最后终于成功的贴了上去。

其实作为CSDN blog一个使用者,我的要求并不高:只要能写blog,能够正常访问就可以了。然而就是这么一点基本的要求好像也得不到满足。

我不知道大家有没有这样的体验:其实软件使用者要求的东西都很基本,而现在软件做得越来越复杂,有相当大一部分是在于软件开发者把自己的注意力放在了一些附加功能(这些功能可能让用户感到惊喜,但是如果没有它们用户也不会不满意)上,而真正用户的要求却得不到满足。所以大家在设计程序的时候,一定要明白,有时候简单就是一种美,把时间花费到真正有价值的地方去。

OK,回到我们的主题上来。在这一节中,我将给大家介绍swt的事件模式。在前面我们也提到过,写一个swt程序,无非就是分几步走。其中比较需要费心的就是布置好用户界面和处理各种事件。

添加了事件处理的Hello,world!

其实swt中处理事件非常简单,对应于各种事件都有相应的listener类,如果一种事件叫做Xyz,那么对应的listener类就是XyzListener。比如对应于鼠标事件的有MouseListener,对应于键盘事件的就是KeyListener。而在每种widget中,对于它可以处理的事件都有addXyzListener方法,只要把对应的listener实例作为参数传给它就可以了。

为了更加清楚的说明,我们先来看下面一段程序:

 1 public class EventDemo {
 2 
 3     private Shell _shell;
 4 
 5     public EventDemo() {
 6         Display display = new Display();
 7         Shell shell = new Shell(display,SWT.SHELL_TRIM);
 8         setShell(shell);
 9         RowLayout layout=new RowLayout();
10         shell.setLayout(layout);
11         shell.setText("Event demo");
12         
13         Button button=new Button(shell,SWT.PUSH | SWT.CENTER);
14         button.setText("Click me!");
15 
16         button.addSelectionListener(new SelectionListener(){
17 
18             public void widgetSelected(SelectionEvent event) {
19                 handleSelectionEvent();
20             }
21 
22             public void widgetDefaultSelected(SelectionEvent event) {
23             }     
24         });
25         shell.setBounds(200,300,100,100);
26         shell.open();
27 
28         while (!shell.isDisposed()) {
29             if (!display.readAndDispatch()) {
30                 display.sleep();
31             }
32         }
33         display.dispose();    
34         
35     }
36 
37     protected void handleSelectionEvent() {
38         MessageBox dialog=new MessageBox(getShell(),SWT.OK|SWT.ICON_INFORMATION);
39         dialog.setText("Hello");
40         dialog.setMessage("Hello,world!");
41         dialog.open();
42     }
43 
44     /**
45      * @param args
46      */
47     public static void main(String[] args) {
48 
49         EventDemo eventdemo=new EventDemo();
50     }
51 
52     /**
53      * @return Returns the _shell.
54      */
55     public Shell getShell() {
56         return _shell;
57     }
58 
59     /**
60      * @param _shell The _shell to set.
61      */
62     public void setShell(Shell shell) {
63         this._shell =shell;
64     }
65 }
66 

代码段 6

你可以看到在这段程序中,我们只创建了一个Button,随后调用了它的addSelectionListener()方法,在这个新创建的Listener,我们只为widgetSelected方法添加了代码,并在其中创建了一个对话框。实际运行效果如下图,其中那个标有Hello,world的对话框是按了按钮以后出现的:

 

6

如果总结一下,我们可以得出处理事件的几个步骤:

1.      针对你所处理的事件,找出合适的XyzListener接口

2.      编写一个新的类,这个类实现了XyzListener接口

3.      在你所感兴趣的事件中编写处理代码,而对于那些你不感兴趣的方法可以让它们保持空白(就像实例中的widgetDefaultSelected()方法)一样

让事件处理更加简单:使用适配器(adapter)

有时候我们可能会感觉这样仍然不够简单,比如我只对SelectionListener中的widgetSelected()方法感兴趣,但是为了能够通过编译器的编译,我却不得不写一个空白的widgetDefaultSelected()方法(因为SelectionListener是一个接口,你必须实现它所有的方法)。

幸运的是,swt帮我们解决了这个问题,途径就是使用adapter。在swt中,对应于一个XyzListener都有一个XyzAdapter,adapter都是抽象类并且实现了对应的listener接口,它为对应listener接口中的每个方法都定义了一个默认实现(基本上就是什么都不做),我们在使用时候只需要override掉自己感兴趣的方法就可以了。

结合上一小节中的代码,如果使用SelectionAdapter代替SelectionListener的话,我们的代码就可以这样写:

button.addSelectionListener(new SelectionAdapter(){
            
public void widgetSelected(SelectionEvent event) {
                handleSelectionEvent();
            }
        });

这样是不是很方便呢?

EventObject:事件处理的附加信息

在处理各种事件时,我们需要一些附加信息,而EventObject给我们提供了这些信息。

我们先来看下面这个简单的小程序,在这段程序中,我们创建了两个文本框,当在第一个文本框输入时,第二个文本框中显示输入的字符。

 1 public class EventDemo2 {
 2 
 3     Text logText;
 4     
 5     public EventDemo2() {
 6         Display display = new Display();
 7         Shell shell = new Shell(display,SWT.SHELL_TRIM);
 8         
 9         GridLayout layout=new GridLayout();
10         layout.numColumns=2;
11         shell.setLayout(layout);
12         shell.setText("Event demo");
13         
14         Label label1=new Label(shell,SWT.RIGHT);
15         label1.setText("text1:");
16         Text text1=new Text(shell,SWT.NONE);
17         
18         text1.addKeyListener(new KeyAdapter(){
19             public void keyPressed(KeyEvent e) {
20                 Text t=getLogText();
21                 String s=t.getText();
22                 t.setText(String.valueOf(e.character));
23             } 
24         }
25         );
26         
27         Label label2=new Label(shell,SWT.RIGHT);
28         label2.setText("text2:");
29         Text text2=new Text(shell,SWT.NONE);
30         text2.setEditable(false);
31         text2.setBackground(new Color(display,255,255,255));
32         setLogText(text2);
33         
34         shell.pack();
35         shell.open();
36 
37         while (!shell.isDisposed()) {
38             if (!display.readAndDispatch()) {
39                 display.sleep();
40             }
41         }
42         display.dispose();           
43     }
44     /*