Java桌面应用程序设计:SWT简介

Java桌面应用程序设计:SWT简介,第1张

Java语言的声望和它在桌面应用程序(GUI程序)所取得的成就显然极不相符 至今仍然很少能看到非常成功Java桌面程序 虽然有JBuilder Netbean JProbe等大型软件作为代表 但这仍不能证明Java的GUI程序是成功的 它们的外观总是和同一 *** 作系统平台下的其它软件显得格格不入 对机器配置的需求也似乎永无止境 这使得它们只能被一些总是拥有当前最高性能PC的程序员们所容忍 或是那些不在乎金钱和时间的专业用户所接受 对绝大多数计算机使用者来说 AWT或SWING代表着怪异的界面和无法接受的速度 Standard Widget Toolkit(SWT)或许是Java这一噩梦的终结者 广大Java程序员终于可以开发出高效率的GUI程序 它们拥有标准的外观 几乎没有人能看出你的程序是用Java写出来的 更为重要的是 这些程序是跨平台的

SWT本身仅仅是Eclipse组织为了开发Eclipse IDE环境所编写的一组底层图形界面 API 或许是无心插柳 或是有意为之 至今为止 SWT无论是在性铅戚能和外观上 都超越了SUN公司提供的AWT和SWING 目前Eclipse IDE已经开发到了 版本 SWT已经十分稳定 这里指的稳定应该包含两层意思

一是指性能上的稳定 其中的关键是源于SWT的设计理念 SWT最大化了 *** 作系统的图形构件API 就是说只要 *** 作系统提供了相应图形的构件 那么SWT只是简单应用JNI技术调用它们 只有那些 *** 作系统中不提供的构件 SWT才自己去做一个模拟的槐带陵实现 可以看出SWT的性能上的稳定大多时候取决于相应 *** 作系统图形构件的稳定性

另一个稳定是指SWT API包中的类 方法的名称和结构已经少有改变 程序员不用担心由于Eclipse组织开发进度很快(Eclipse IDE每天都会有一个Nightly版本的发布) 而导致自己的程序代码变化过大 从一个版本的SWT更新至另一版本 通常只需要简单将SWT包换掉就可以了

第一个SWT程序

下面让我们开始一个SWT程序 (注意 以下的例子和说明主要针对Windows平台 其它的 *** 作系统应该大同小异) 首先要在Eclipse安装文件中找到SWT包 Eclipse组织并不提供单独的SWT包下载 必须下载完整的Eclipse开发环境才能得到SWT包 SWT是作为Eclipse开发环境的一个插件形式存在 可以在${你的eclipse安装路径}\plugins路径下的众多子目录下去搜索SWT JAR文件 在找到的JAR文件中包含了SWT全行宏部的Java类文件 因为SWT应用了JNI技术 因此同时也要找到相对应的JNI本地化库文件 由于版本和 *** 作平台的不同 本地化库文件的名称会有些差别 比如SWT WIN DLL是Window平台下Eclipse Build 的动态库 而在Unix平台相应版本的库文件的扩展名应该是 so 等等 注意的是 Eclipse是一个开放源代码的项目 因此你也可以在这些目录中找到SWT的源代码 相信这会对开发很有帮助 下面是一段打开空窗口的代码(只有main方法)

import e one examplepublic class OpenShell{ public static void main(String [] args) {Display display = new Display()Shell shell = new Shell(display)shell open()// 开始事件处理循环 直到用户关闭窗口while (!shell isDisposed()) { if (!display readAndDispatch())display sleep()}display dispose() }}

确信在CLASSPATH中包括了SWT JAR文件 先用Javac编译例子程序 编译无错后可运行java Djava library path=${你的SWT本地库文件所在路径} e one example OpenShell 比如SWT WIN DLL件所在的路径是C:\swtlib 运行的命令应该是java Djava library path=c:\swtlib e one example OpenShell 成功运行后 系统会打开了一个空的窗口

剖析SWT API

下面再让我们进一步分析SWT API的组成 所有的SWT类都用 eclipse swt做为包的前缀 下面为了简化说明 我们用*号代表前缀 eclipse swt 比如* widgets包 代表的是 eclipse swt widgets包

我们最常用的图形构件基本都被包括在* widgets包中 比如Button Combo Text Label Sash Table等等 其中两个最重要的构件当数Shell和Composite Shell相当于应用程序的主窗口框架 上面的例子代码中就是应用Shell构件打开一个空窗口 Composite相当于SWING中的Panel对象 充当着构件容器的角色 当我们想在一个窗口中加入一些构件时 最好到使用Composite作为其它构件的容器 然后再去* layout包找出一种合适的布局方式 SWT对构件的布局也采用了SWING或AWT中Layout和Layout Data结合的方式 在* layout包中可以找到四种Layout和与它们相对应的布局结构对象(Layout Data) 在* custom包中 包含了对一些基本图形构件的扩展 比如其中的CLabel 就是对标准Label构件的扩展 上面可以同时加入文字和图片 也可以加边框 StyledText是Text构件的扩展 它提供了丰富的文本功能 比如对某段文字的背景色 前景色或字体的设置 在* custom包中也可找到一个新的StackLayout布局方式

SWT对用户 *** 作的响应 比如鼠标或键盘事件 也是采用了AWT和SWING中的Observer模式 在* event包中可以找到事件监听的Listener接口和相应的事件对象 例如常用的鼠标事件监听接口MouseListener MouseMoveListener和MouseTrackListener 及对应的事件对象MouseEvent

* graphics包中可以找到针对图片 光标 字体或绘图的API 比如可通过Image类调用系统中不同类型的图片文件 通过GC类实现对图片 构件或显示器的绘图功能

对不同平台 Eclipse还开发了一些富有针对性的API 例如 在Windows平台 可以通过* ole win 包很容易的调用ole控件 这使Java程序内嵌IE浏览器或Word Excel等程序成为可能!

更复杂的程序

下面让我们展示一个比上面例子更加复杂一些的程序 这个程序拥有一个文本框和一个按键 当用户点击按键的时候 文本框显示一句欢迎信息

为了文本框和按键有比较合理的大小和布局 这里采用了GridLayout布局方式 这种布局是SWT中最常用也是最强大的布局方式 几乎所有的格式都可能通过GridLayout去达到 下面的程序也涉及到了如何应用系统资源(Color) 以及如何释放系统资源

private void initShell(Shell shell) { //为Shell设置布局对象 GridLayout gShellLay = new GridLayout() shell setLayout(gShellLay) //构造一个Composite构件作为文本框和按键的容器 Composite panel = new Composite(shell SWT NONE) //为Panel指定一个布局结构对象 这里让Panel尽可能的占满Shell 也就是全部应用程序窗口的空间  GridData gPanelData = new GridData(GridData GRAB_HORIZONTAL| GridData GRAB_VERTICAL|GridData FILL_BOTH) panel setLayoutData(gPanelData) //为Panel也设置一个布局对象 文本框和按键将按这个布局对象来显示  GridLayout gPanelLay = new GridLayout() panel setLayout(gPanelLay) //为Panel生成一个背景色 final Color bkColor = new Color(Display getCurrent() ) panel setBackground(bkColor) //生成文本框 final Text text = new Text(panel SWT MULTI|SWT WRAP) //为文本框指定一个布局结构对象 这里让文本框尽可能的占满Panel的空间  GridData gTextData = new GridData (GridData GRAB_HORIZONTAL| GridData GRAB_VERTICAL|GridData FILL_BOTH) text setLayoutData(gTextData) //生成按键 Button butt = new Button(panel SWT PUSH) butt setText( Push ) //为按键指定鼠标事件 butt addMouseListener(new MouseAdapter(){public void mouseDown(MouseEvent e){ //当用户点击按键的时候 显示信息 text setText( Hello SWT )} } //当主窗口关闭时 会触发DisposeListener 这里用来释放Panel的背景色  shell addDisposeListener(new DisposeListener(){public void widgetDisposed(DisposeEvent e) { bkColor dispose()} }}

把这段代码中的方法initShell()加入到第一个打开空窗口的例子中 得到的是一段能成功运行的完整GUI应用程序 运行方法可参考第一个例子

系统资源的管理

在一个图形化的 *** 作系统中开发程序 都要调用系统中的资源 如图片 字体 颜色等 通常这些资源都是有限的 程序员务必非常小心的使用这些资源 当不再使用它们时 就请尽快释放 不然 *** 作系统迟早会油尽灯枯 不得不重新启动 更严重的会导致系统崩溃 SWT是用Java开发的 Java语言本身的一大优势就是JVM的 垃圾回收机制 程序员通常不用理会变量的释放 内存的回收等问题 那么对SWT而言 系统资源的 *** 作是不是也是如此?答案是一个坏消息 一个好消息

坏消息是SWT并没采用JVM的垃圾回收机制去处理 *** 作系统的资源回收问题 一个关键的因素是因为JVM的垃圾回收机制是不可控的 也就是说程序员不能知道 也不可能做到在某一时刻让JVM回收资源!这对系统资源的处理是致命的 试想你的程序希望在一个循环语句中去查看数万张图片 常规的处理方式是每次调入一张 查看 然后就立即释放该图片资源 而后在循环调入下一张图片 这对 *** 作系统而言 任何时刻程序占用的仅仅是一张图片的资源 但如果这个过程完全交给JVM去处理 也许会是在循环语句结束后 JVM才会去释放图片资源 其结果可能是你的程序还没有运行结束 *** 作系统已经宕掉

但下面的好消息也许会让这个坏消息变得无关紧要 对于SWT 只需了解两条简单的 黄金 法则就可以放心的使用系统资源!之所以称为黄金法则 一是因为少 只有两条 二是因为它们出奇的简单 第一条是 谁占用 谁释放 第二条是 父构件被销毁 子构件也同时被销毁 第一条原则是一个无任何例外的原则 只要程序调用了系统资源类的构造函数 程序就应该关心在某一时刻要释放这个系统资源 比如调用了

Font font = new Font (display Courier SWT NORMAL)

那么就应该在不在需要这个Font的时候调用

font dispose()

对于第二个原则 是指如果程序调用某一构件的dispose()方法 那么所有这个构件的子构件也会被自动调用dispose()方法而销毁 通常这里指的子构件与父构件的关系是在调用构件的构造函数时形成的 比如

Shell shell = new Shell()Composite parent = new Composite(shell SWT NULL)Composite child = new Composite(parent SWT NULL)

其中parent的父构件是shell 而shell则是程序的主窗口 所以没有相应的父构件 同时parent又包括了child子构件 如果调用shell dispose()方法 应用第二条法则 那么parent和child构件的dispose()方法也会被SWT API自动调用 它们也随之销毁

   线程问题

在任何 *** 作平台的GUI系统中 对构件或一些图形API的访问 *** 作都要被严格同步并串行化 例如 在一个图形界面中的按键构件可被设成可用状态(enable)或禁用状态(disable) 正常的处理方式是 用户对按键状态设置 *** 作都要被放入到GUI系统的事件处理队列中(这意味着访问 *** 作被串行化) 然后依次处理(这意味着访问 *** 作被同步) 想象当按键可用状态的设置函数还没有执行结束的时候 程序就希望再设置该按键为禁用状态 势必会引起冲突 实际上 这种 *** 作在任何GUI系统都会触发异常

Java语言本身就提供了多线程机制 这种机制对GUI编程来说是不利的 它不能保证图形构件 *** 作的同步与串行化 SWT采用了一种简单而直接的方式去适应本地GUI系统对线程的要求 在SWT中 通常存在一个被称为 用户线程 的唯一线程 只有在这个线程中才能调用对构件或某些图形API的访问 *** 作 如果在非用户线程中程序直接调用这些访问 *** 作 那么SWTExcepiton异常会被抛出 但是SWT也在* widget Display类中提供了两个方法可以间接的在非用户线程的进行图形构件的访问 *** 作 这是通过syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现 例如

//此时程序运行在一个非用户线程中 并且希望在构件panel上加入一个按键

Display getCurrent() asyncExec(new Runnable() { public void run() {Button butt = new Button(panel SWT PUSH)butt setText( Push ) }})

方法syncExec()和asyncExec()的区别在于前者要在指定的线程执行结束后才返回 而后者则无论指定的线程是否执行都会立即返回到当前线程

SWT的扩展 JFace

JFace与SWT的关系好比Microsoft的MFC与SDK的关系 JFace是基于SWT开发 其API比SWT更加易于使用 但功能却没SWT来的直接 比如下面的代码应用JFace中的MessageDialog打开一个警告对话框

MessageDialog openWarning(parent Warning Warning message )

如果只用SWT完成以上功能 语句不会少于 行!

JFace原本是为更加方便的使用SWT而编写的一组API 其主要目的是为了开发Eclipse IDE环境 而不是为了应用到其它的独立应用程序 因此在Eclipse 版本之前 很难将JFace API完整的从Eclipse的内核API中剥离出来 总是要多多少少导入一些非JFace以外的Eclipse核心代码类或接口才能得到一个没有任何编译错误的JFace开发包 但目前Eclipse组织似乎已经逐渐意识到了JFace在开发独立应用程序起到的重要作用 在开发的 版本中 JFace也开始变成了和SWT一样的完整独立的开发包 只是这个开发包还在变动中(笔者写本文时 应用的Eclipse M 版本) JFace开发包的包前缀是以 eclipse jface开头 JAR包的源代码也和SWT一样 也在${你的eclipse安装路径}\plugins路径下去找

对开发人员来说 在开发一个图形构件的时候 比较好的方式是先到JFace包去找一找 看是不是有更简洁的实现方法 如果没有再用SWT包去自己实现 比如JFace为对话框提供了很好的支持 除了各种类型的对话框(比如上面用的MessageDialog 或是带有Title栏的对话框) 如要实现一个自定义的对话框也最好从JFace中的Dialog类继承 而不是从SWT中的* widget Dialog继承

应用JFace中的Preference包中的类很容易为自己的软件做出一个很专业的配置对话框 对于Tree Table等图形构件 它们在显示的同时也要和数据关联 例如Table中显示的数据 在JFace 中的View包中为此类构件提供了Model View方式的编程方法 这种方法使显示与数据分开 更加利于开发与维护 JFace中提供最多的功能就是对文本内容的处理 可以在 eclipse jface text * 包中找到数十个与文本处理相关类

与应用程序更近一步

Java程序通常是以class文件的方式发布的 运行class需要JRE或JDK的支持 这又是Java GUI程序的另一个致命的弱点 想象对一个面向广大用户的应用程序来说 无论你的程序功能有多简单 或是你的代码十分的精简 你都不得不让用户去下载一个 M的JRE 那是多么令人沮丧的一件事 而且对程序员来说 Class通常意味着源代码的暴露 反编译的工具让那些居心叵测的人轻易得到你的源代码 虽然有很多对Class的加密方法 但那总是以牺牲性能为代价的 好在我们还有其它的方式可用 把Class编译成exe文件!

lishixinzhi/Article/program/Java/gj/201311/27737

在窗口系统中 程序一般都是以事件驱动的 SWT的Control类实现了一些事件监听的注册方法 其子类都可以通过这些方法注册鼠标和键盘的监听器 通过实现这些监听器的接口 窗口组件烂洞就能响应相应的鼠标和键盘事件 Control类是窗口组件类的基类 它定义了基本的事件监听方法 有如下一些

addControlListener addFocusListener addHelpListener addKeyListener addMouseListener addMouseTrackListener addMouseMoveListener addPaintListener addTraverseListener

添加事件监听器步骤如下 创建事件监听器 例如 new KeyListener()… 通过Control类的子类添加事件监听器 例如 text addKeyListener() 常用事件有鼠标事件 键盘事件 焦点事件 窗口控制事件和选择事件 Control类的子类也可以定义添加相关的监听方法

  鼠标事件 在窗口系统中 鼠标基本上是饥物枯必备的设备 一般来说 窗口中鼠标有鼠标单击 鼠标双击 鼠标进入窗口 鼠标退出窗口及鼠标移动等事件 在SWT中 事件的响应是通过相应接口实现的 每个组件可以添加相应的事件响应实例来监听事件 例如 button addMouseListener(listener) 表示在button组件上添加鼠标的相应响应事件实例 其中 listener为实现监听器对象 下面就具体的鼠标事件进行介绍 MouseListener接口 在SWT中 通过实现MouseListener接口来响应鼠标的按下 松开及双击事件 MouseListener接口如例程 所示 例程 MouseListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface MouseListener extends SWTEventListener { public void mouseDoubleClick(MouseEvent e)public void mouseDown(MouseEvent e)public void mouseUp(MouseEvent e)}

其中 mouseDoubleClick表示鼠标双击事件响应方法 mouseDown表示鼠标键按下事件的响应方法 mouseUp表示鼠标键起来事件的响应方法 MouseEvent为系统传入的鼠标事件的参数 MouseEvent中的button属性表示鼠标的按钮值 例如e button等于 表示鼠标左键按下 按钮值对应鼠标按钮如表 所示

在程序中 开发人员可以根据e button的值判断当前用蚂漏户按的是哪一个鼠标键 从而确定采用什么 *** 作 MouseMoveListener接口 在SWT中 通过实现MouseMoveListener接口来响应鼠标的移动事件 MouseMoveListener接口如例程 所示 例程 MouseMoveListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface MouseMoveListener extends SWTEventListener { public void mouseMove(MouseEvent e)}

MouseMoveListener只有mouseMove方法 用来响应窗口中鼠标移动事件 MouseTrackListener接口 在SWT中 通过实现MouseTrackListener接口来响应鼠标进入窗口 鼠标退出窗口和鼠标停放在窗口上的事件 MouseTrackListener接口如例程 所示 例程 MouseTrackListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface MouseTrackListener extends SWTEventListener { public void mouseEnter(MouseEvent e)public void mouseExit(MouseEvent e)public void mouseHover(MouseEvent e)}

其中 mouseEnter表示鼠标进入窗口事件的响应方法 mouseExit表示鼠标退出窗口事件的响应方法 mouseHover表示鼠标停放在窗口上事件的响应方法 鼠标事件实例 为了更深入地理解鼠标事件 下面通过具体的实例演示如何响应鼠标事件 该程序只是当事件触发时简单地打印出相应信息 在具体的实例中 读者可以根据需要进行修改 代码如例程 所示 例程 MouseEventExample java

/** * 为了节省篇幅 所有的import类已经被注释 * 读者可以通过ctrl+shift+o快捷键 自动引入所依赖的类 * 如果有问题可发邮件到 * */ public class MouseEventExample implements MouseListener MouseMoveListener MouseTrackListener { //显示信息的标签 Label myLabel = nullShell shell = nullpublic MouseEventExample() { } public void run() { Display display = new Display()Shell shell = new Shell(display)shell setLayout(new GridLayout())shell setSize( )shell setText( Mouse Event Example )myLabel = new Label(shell SWT BORDER)myLabel setText( I ain t afraid of any old mouse )//在当前窗口上添加鼠标响应事件 shell addMouseListener(this)shell addMouseMoveListener(this)shell addMouseTrackListener(this)shell open()while (!shell isDisposed()) { if (!display readAndDispatch()) { display sleep()} } display dispose()} public static void main(String[] args) { new MouseEventExample() run()} public void mouseDoubleClick(MouseEvent e) { myLabel setText( Double Click + e button + at: + e x + + e y)System out println( Double Click + e button + at: + e x + + e y)} public void mouseDown(MouseEvent e) { myLabel setText( Button + e button + Down at: + e x + + e y)System out println( Button + e button + Down at: + e x + + e y)} public void mouseUp(MouseEvent e) { myLabel setText( Button + e button + Up at: + e x + + e y)System out println( Button + e button + Up at: + e x + + e y)} public void mouseMove(MouseEvent e) { myLabel setText( Mouse Move at: + e x + + e y)System out println( Mouse Move at: + e x + + e y)} public void mouseEnter(MouseEvent e) { myLabel setText( Mouse Enter at: + e x + + e y)System out println( Mouse Enter at: + e x + + e y)} public void mouseExit(MouseEvent e) { myLabel setText( Mouse Exit at: + e x + + e y)System out println( Mouse Exit at: + e x + + e y)} public void mouseHover(MouseEvent e) { myLabel setText( Mouse Hover at: + e x + + e y)System out println( Mouse Hover at: + e x + + e y)} }

MouseEventExample类实现了MouseListener MouseMoveListener和MouseTrackListener 个接口 并通过 shell addMouseListener(this)shell addMouseMoveListener(this)和 shell addMouseTrackListener(this)把自己作为监听器添加到了窗口中 程序运行效果如图 所示

图 鼠标事件实例

 

    键盘事件 键盘事件是最简单 也是最常用的事件 一般来说 键盘事件有两种 键按下和键松开 SWT通过KeyListener响应键盘事件 KeyListener接口 在SWT中 通过实现KeyListener接口来响应键按下和松开的事件 KeyListener接口如例程 所示 例程 KeyListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface KeyListener extends SWTEventListener { public void keyPressed(KeyEvent e)public void keyReleased(KeyEvent e)}

其中 keyPressed表示键按下事件的响应方法 keyReleased表示键松开事件的响应方法 KeyEvent为系统传入的键盘事件的参数 用户可以通过KeyEvent参数找到相应的按键值 键盘事件实例 为了更深入地了解键盘事件 下面通过具体的实例演示如何响应键盘事件 该程序只是当事件触发时简单地打印出相应信息 在具体的实例中 读者可以根据需要进行修改 代码如例程 所示 例程 KeyListenerExample java

public class KeyListenerExample { Display displayShell shellKeyListenerExample() { display = new Display()shell = new Shell(display)shell setSize( )shell setText( A KeyListener Example )Text text = new Text(shell SWT BORDER)text setBounds( )text addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { System out println( key Pressed +e character)} public void keyReleased(KeyEvent e) { System out println( key Released +e character)} })shell open()while (!shell isDisposed()) { if (!display readAndDispatch()) display sleep()} display dispose()} public static void main(String[] args) { new KeyListenerExample()} }

程序中通过匿名内部类实现监听器 这种方式在实例开发中会经常用到 另外可以通过KeyEvent取得按键的值 如上例的 e character 得到按键的字符 程序运行效果如图 所示

图 键盘事件

                                                                               

焦点事件 在窗口系统中 当组件获得输入焦点或失去焦点时将触发相应的事件 SWT通过FocusListener监听焦点事件 FocusListener接口 在SWT中 通过实现FocusListener接口来响应获得焦点和失去焦点的事件 FocusListener接口如例程 所示 例程 FocusListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface FocusListener extends SWTEventListener { public void focusGained(FocusEvent e)public void focusLost(FocusEvent e)}

其中 focusGained表示组件获得焦点事件的响应方法 focusLost表示组件失去焦点事件的响应方法 FocusEvent为系统传入的焦点事件的参数 用户可以通过FocusEvent参数找到相应的组件 焦点事件实例 为了更深入地理解焦点事件 下面通过具体的实例演示如何响应焦点事件 该程序只是简单地改变当前获得焦点和失去焦点组件的显示信息 在具体的实例中 读者可以根据需要进行修改 代码如例程 所示 例程 FocusListenerExample java

public class FocusListenerExample { public static void main(String[] args) { Display display = new Display()Shell shell = new Shell(display)shell setLayout(new GridLayout( true))shell setText( One Potato Two Potato )//新建焦点监听器 FocusListener listener = new FocusListener() { public void focusGained(FocusEvent event) { //获得触发事件的组件 Button button = (Button) event getSource()//焦点获得时改变显示文本 button setText( I m It! )} public void focusLost(FocusEvent event) { //获得触发事件的组件 Button button = (Button) event getSource()//焦点获得时改变显示文本 button setText( Pick Me! )} }for (int i = i <i++) { Button button = new Button(shell SWT PUSH)button setLayoutData(new GridData(GridData FILL_HORIZONTAL))button setText( Pick Me! )button addFocusListener(listener)} shell pack()shell open()while (!shell isDisposed()) { if (!display readAndDispatch()) { display sleep()} } display dispose()} }

程序中显示了 个按钮 并为按钮添加上了焦点监听器 程序运行效果如图 所示

图 焦点事件实例

 

  窗口控制事件 在窗口系统中 当组件被移动或改变大小时将触发相应的事件 SWT通过ControlListener监听窗口控制事件 ControlListener接口 在SWT中 通过实现ControlListener接口来响应组件被移动或改变大小的事件 ControlListener接口如例程 所示 例程 ControlListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface ControlListener extends SWTEventListener { public void controlMoved(ControlEvent e)public void controlResized(ControlEvent e)}

其中 controlMoved表示组件被移动事件的响应方法 controlResized表示组件被改变大小事件的响应方法 ControlEvent为系统传入的窗口控制事件的参数 用户可以通过ControlEvent参数找到相应的组件 窗口控制事件实例 为了更深入地理解窗口控制事件 下面通过具体的实例演示如何响应窗口控制事件 该程序只是简单地打印组件被移动或改变大小的信息 在具体的实例中 读者可以根据需要进行修改 代码如例程 所示 例程 ControlListenerExample java

public class ControlListenerExample { public void run() { Display display = new Display()Shell shell = new Shell(display)shell addControlListener(new ControlListener() { public void controlMoved(ControlEvent e) { System out println( control move )} public void controlResized(ControlEvent e) { System out println( control resize )} } )shell pack()shell open()while (!shell isDisposed()) { if (!display readAndDispatch()) { display sleep()} } display dispose()} public static void main(String[] args) { new ControlListenerExample() run()} }

上例显示的只是一个空白的窗口 当用户移动窗口或改变窗口大小时 将会触发监听器所实现的事件

 

  选择事件 SWT的很多组件都实现了选择组件事件的监听机制 例如按钮 菜单项的选择 当选择了相关的菜单项或组件时 将触发相应的事件 SelectionListener接口 在SWT中 通过实现SelectionListener接口来响应选择组件事件 SelectionListener接口如例程 所示 例程 SelectionListener java

package eclipse swt eventsimport eclipse swt internal SWTEventListenerpublic interface SelectionListener extends SWTEventListener { public void widgetSelected(SelectionEvent e)public void widgetDefaultSelected(SelectionEvent e)}

其中 widgetSelected表示组件被选择事件的响应方法 widgetDefaultSelected表示组件默认选择事件的响应方法 SelectionEvent为系统传入的选择事件的参数 选择组件事件实例 为了更深入地理解选择组件事件 下面通过具体的实例演示如何响应选择组件事件 该程序只是简单地打印组件被移动或改变大小的信息 在具体的实例中 读者可以根据需要进行修改 代码如例程 所示 例程 SelectonListenerExample java

public class SelectonListenerExample { public static void main(String[] args) { Display display = new Display()final Shell mainShell = new Shell(display)Button button = new Button(mainShell SWT PUSH)button setText( Close Me! )button setBounds( )// 添加选择组件事件 button addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent event) { System out println( select button )mainShell close()} public void widgetDefaultSelected(SelectionEvent e) { // 不执行任何 *** 作 } })mainShell open()while (!mainShell isDisposed()) { if (!display readAndDispatch()) { display sleep()} } display dispose()} }

上例中只是添加了一个按钮 当选择按钮时关闭当前窗口

其他常用事件 SWT中为了实现特定的功能 很多组件都提供了特定事件的响应 本节将通过实例介绍HelpListener VerifyListener和ModifyListener 个特定的事件监听器 HelpListener VerifyListener和ModifyListener监听器的功能 HelpListener监听器通过helpRequested(HelpEvent e)方法响应用户的帮助请求事件 当用户在组件获得焦点后按【F 】键将触发此事件 VerifyListener监听器通过verifyText(VerifyEvent e)方法响应校验输入事件 此监听器只对文本输入校验 当用户输入了数据后 verifyText方法将通过设置VerifyEvent中的doit属性判断输入是否正确 从而确定修改是否有效 doit属性为true时修改有效 即 e doit = trueModifyListener监听器通过modifyText(ModifyEvent e)方法响应文本被修改的事件 此监听器只对文本输入校验 提示 如果VerifyListener监听器和ModifyListener监听器同时存在的话 会先响应校验输入事件 如果校验成功再响应修改事件 HelpListener VerifyListener和ModifyListener监听器实例 在此实例中 用户可以输入华氏温度和摄氏温度 通过监听器判断输入是否正确及计算相应的摄氏温度和华氏温度 另外 还可以按【F 】键获得当前组件的信息 代码如例程 所示 例程 MultipleListenersExample java

public class MultipleListenersExample implements HelpListener VerifyListener ModifyListener { private static final double FIVE_NINTHS = / private static final double NINE_FIFTHS = / private Text fahrenheitprivate Text celsiusprivate Label helppublic void run() { Display display = new Display()Shell shell = new Shell(display)shell setText( Temperatures )createContents(shell)shell pack()shell open()while (!shell isDisposed()) { if (!display readAndDispatch()) { display sleep()} } display dispose()} private void createContents(Shell shell) { shell setLayout(new GridLayout( true))new Label(shell SWT LEFT) setText( Fahrenheit: )fahrenheit = new Text(shell SWT BORDER)GridData data = new GridData(GridData FILL_HORIZONTAL)data horizontalSpan = fahrenheit setLayoutData(data)fahrenheit setData( Type a temperature in Fahrenheit )// 为华氏温度文本框添加监听器 fahrenheit addHelpListener(this)fahrenheit addVerifyListener(this)fahrenheit addModifyListener(this)new Label(shell SWT LEFT) setText( Celsius: )celsius = new Text(shell SWT BORDER)data = new GridData(GridData FILL_HORIZONTAL)data horizontalSpan = celsius setLayoutData(data)celsius setData( Type a temperature in Celsius )//为摄氏温度文本框添加监听器 celsius addHelpListener(this)celsius addVerifyListener(this)celsius addModifyListener(this)help = new Label(shell SWT LEFT | SWT BORDER)data = new GridData(GridData FILL_HORIZONTAL)data horizontalSpan = help setLayoutData(data)} //响应帮助事件 public void helpRequested(HelpEvent event) { help setText((String) event widget getData())}  //响应校验事件 public void verifyText(VerifyEvent event) { event doit = falsechar myChar = event characterString text = ((Text) event widget) getText()if (myChar == &&text length() == ) event doit = trueif (Character isDigit(myChar)) event doit = trueif (myChar == \b ) event doit = true}  //响应文本修改的事件 public void modifyText(ModifyEvent event) { // 删除监听器 从而在modifyText过程中不会触发事件 celsius removeVerifyListener(this)celsius removeModifyListener(this)fahrenheit removeVerifyListener(this)fahrenheit removeModifyListener(this)Text text = (Text) event widgettry { int temp = Integer parseInt(text getText())if (text == fahrenheit) { celsius setText(String valueOf((int) (FIVE_NINTHS * (temp ))))} else { fahrenheit setText(String valueOf((int) (NINE_FIFTHS * temp + )))} } catch (NumberFormatException e) { /* Ignore */ } //添加监听器 celsius addVerifyListener(this)celsius addModifyListener(this)fahrenheit addVerifyListener(this)fahrenheit addModifyListener(this)} public static void main(String[] args) { new MultipleListenersExample() run()} }

程序运行效果如图 所示

图 文本监听器

lishixinzhi/Article/program/Java/ky/201311/27909


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12491853.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存