Java桌面应用措施设计新贵:SWT简介
当前位置:以往代写 > JAVA 教程 >Java桌面应用措施设计新贵:SWT简介
2019-06-14

Java桌面应用措施设计新贵:SWT简介

Java桌面应用措施设计新贵:SWT简介

副标题#e#

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已经开拓到了2.1版本,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-WIN32-2116.DLL是Window平台下Eclipse Build 2116的动态库,而在Unix平台相应版本的库文件的扩展名应该是.so,等等。留意的是,Eclipse是一个开放源代码的项目,因此你也可以在这些目次中找到SWT的源代码,相信这会对开拓很有辅佐。下面是一段打开空窗口的代码(只有main要领)。

import com.e2one.example;
public 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当地库文件地址路径} com.e2one.example.OpenShell,好比SWT-WIN32-2116.DLL件地址的路径是C:\swtlib,运行的呼吁应该是java -Djava.library.path=c:\swtlib com.e2one.example.OpenShell。乐成运行后,系统会打开了一个空的窗口。

分解SWT API

下面再让我们进一步阐明SWT API的构成。所有的SWT类都用org.eclipse.swt做为包的前缀,下面为了简化说明,我们用*号代表前缀org.eclipse.swt,好比*.widgets包,代表的是org.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机关方法。

#p#分页标题#e#

SWT对用户操纵的响应,好比鼠标或键盘事件,也是回收了AWT和SWING中的Observer模式,在*.event包中可以找到事件监听的Listener接口和相应的事件工具,譬喻常用的鼠标事件监听接口MouseListener,MouseMoveListener和MouseTrackListener,及对应的事件工具MouseEvent。

*.graphics包中可以找到针对图片、光标、字体或画图的API。好比可通过Image类挪用系统中差异范例的图片文件。通过GC类实现对图片、构件或显示器的画图成果。

对差异平台,Eclipse还开拓了一些富有针对性的API。譬喻,在Windows平台,可以通过*.ole.win32包很容易的挪用ole控件,这使Java措施内嵌IE欣赏器或Word、Excel等措施成为大概!


#p#副标题#e#

更巨大的措施

下面让我们展示一个比上面例子越发巨大一些的措施。这个措施拥有一个文本框和一个按键,当用户点击按键的时候,文本框显示一句接待信息。

为了文本框和按键有较量公道的巨细和机关,这里回收了GradLayout机关方法。这种机关是SWT中最常用也是最强大的机关方法,险些所有的名目都大概通过GradLayout去到达。下面的措施也涉及到了如何应用系统资源(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(),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才会去释放图片资源,其功效大概是你的措施还没有运行竣事,操纵系统已经宕掉。

#p#分页标题#e#

但下面的好动静也许会让这个坏动静变得无关紧急。对付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自动挪用,它们也随之销毁。

#p#副标题#e#

线程问题

在任何操纵平台的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完成以上成果,语句不会少于30行!

JFace原本是为越发利便的利用SWT而编写的一组API,其主要目标是为了开拓Eclipse IDE情况,而不是为了应用到其它的独立应用措施。因此在Eclipse 2.1版本之前,很难将JFace API完整的从Eclipse的内核API中剥离出来,老是要多几几何导入一些非JFace以外的Eclipse焦点代码类或接谈锋气获得一个没有任何编译错误的JFace开拓包。但今朝Eclipse组织好像已经逐渐意识到了JFace在开拓独立应用措施起到的重要浸染,在正在开拓的2.1版本中,JFace也开始酿成了和SWT一样的完整独立的开拓包,只是这个开拓包还在变换中(笔者写本文时,应用的Eclipse2.1M3版本)。JFace开拓包的包前缀是以org.eclipse.jface开头。JAR包和源代码也和SWT一样,也在${你的eclipse安装路径}\plugins路径下去找。

#p#分页标题#e#

对开拓人员来说,在开拓一个图形构件的时候,较量好的方法是先到JFace包去找一找,看是不是有更简捷的实现要领,假如没有再用SWT包去本身实现。好比JFace为对话框提供了很好的支持,除了各类范例的对话框(好比上面用的MessageDialog,或是带有Title栏的对话框),如要实现一个自界说的对话框也最好从JFace中的Dialog类担任,而不是从SWT中的*.widget.Dialog担任。

应用JFace中的Preference包中的类很容易为本身的软件做出一个很专业的设置对话框。对付Tree、Table等图形构件,它们在显示的同时也要和数据关联,譬喻Table中显示的数据,在JFace中的View包中为此类构件提供了Model-View方法的编程要领,这种要领使显示与数据分隔,越发利于开拓与维护。JFace中提供最多的成果就是对文本内容的处理惩罚。可以在org.eclipse.jface.text.*包中找到数十个与文本处理惩罚相关类。

与应用措施更近一步

Java措施凡是是以class文件的方法宣布的,运行class需要JRE或JDK的支持。这又是Java GUI措施的另一个致命的弱点,想象对一个面向宽大用户的应用措施来说,无论你的措施成果有多简朴,或是你的代码十分的精简,你都不得不让用户去下载一个7、8M的JRE,那是何等令人沮丧的一件事。并且对措施员来说,Class凡是意味着源代码的袒露,反编译的东西让那些故意叵测的人等闲获得你的源代码。固然有许多对Class的加密要领,但那老是以牺牲机能为价钱的。亏得我们尚有其它的方法可用:把Class编译成exe文件!

通过SWT开拓包,简朴、跨平台、靠得住等这些Java语言自己所具有的利益正徐徐融合到图形界面的应用措施开拓中去。因此,我相信Java语言的另一扇乐成之门正在逐渐打开。

    关键字:

在线提交作业