AWT 和 SWING 的强大竞争者:SWT 简介(2)

2008-02-23 10:07:59来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


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(),200,0,200);
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", 10, 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)这两个方法去实现的。例如:

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Pass J2ME (1) - MIDP State

下一篇:jsp mysql制作简单的留言板(6)