博客网 >

Eclipse In Action - 附录D. 介绍SWT
作者:分类:默认分类标签:
《Eclipse In Action》是一本面向Eclipse初学者的教程,对Java开发有兴趣的人也可以读一读。
笔者参与了该书的翻译工作,并同步发布译稿,希望各位指正。

附录D. 介绍SWT


翻译:Addone Squid[天堂鱿鱼](addone@gmail.com
  本附录介绍了标准窗口小部件工具包(SWT)并特别介绍了:
  • SWT是什么
  • SWT的体系结构
  • SWT和事件、线程
  • 如何运行SWT代码
  SWT是由IBM开发的,作为抽象窗口工具包(AWT)和Swing的替代品的一种工具包。IBM的目标是创建一种GUI工具包,其观感和行为都像是系统中通常的窗口小部件,并且性能上也具有相同的速度。在本附录中,我们会观察AWT和Swing的行为,并和IBM采取的方法相比较。然后,我们将讨论如何使用SWT,指出在使用中比较重要的概念和问题。

D.1 什么是标准窗口小部件工具包?


  Eclipse技术概述(http://www.eclipse.org/whitepapers/eclipse-overview.pdf)将SWT描述为一种“与本地窗口系统结合但使用操作系统无关的API的窗口小部件集及图形库”。在深入分析这种表述之前,让我们来看看在Java 1.0版本中提供的第一个图形API:抽象窗口工具包(AWT)。AWT提供了一套API来构建如标签、文本框、按钮、列表和菜单之类的图形组件,并指派操作系统来提供这些组件的特定实现。当你构建一个文本框时,操作系统构造它自己的文本框并显示在程序窗体中--Windows上的Java文本框看起来就像一个Windows文本框,而Macintosh上的Java文本框看起来就像一个Macintosh文本框。
  AWT的问题是Sun仅仅实现了在Java支持的所有平台中共有的那些窗口小部件。为了解决这个问题,Sun和Netscape合作引入了Swing,这是创建完全跨平台的窗口小部件集的一次尝试。为了达到这个目标,他们用Java来编写所有的东西,而不是指派给操作系统。这种方法让Java在界面方面变得更有用,但代价是:
  • 这些控件和它们运行其上的平台的外观并不相符。
  • 相对于本地实现来说,这些控件的性能要差得多。
  Sun试图通过为每种操作系统都开发被称为“可插入式观感”的东西来解决第一个问题。 然而,尽管这种方法解决了部分问题,Sun却无法跟上操作系统的更新。比如,一种Windows的观感在Windows 95、Windows 98、Windows ME、Windows 2000和Windows XP上看起来都一样,而本地程序则会依赖于运行的是哪个版本,看起来会不一样。
  Sun已经在性能问题上取得了很大进展,但一个模拟组件终究永远也不可能和本地等价组件具有同样好的性能。在JVM中总会存在一个翻译过程,以将模拟组件翻译为一个本地描绘的指令集。
  在Eclipse的开发过程中,IBM研发了针对这个问题的一种新方法,这是Sun的两种方法的某种混合。SWT是一种通过Java本地接口(JNI)来访问本地控件的窗口小部件集。只有在特定的操作系统上不存在的少数几个控件才会进行模拟。这种方法的缺陷是,在Eclipse/SWT部署的每个平台上,都需要有本地库。然而好处是,程序的外观和性能都和本地程序一样。并且,从Eclipse的2.1版开始,在大多数桌面操作系统和Pocket PC上都支持SWT。

D.2 SWT体系结构


  在谈了一些关于SWT是什么的问题后,让我们用图形来再看看它。如图D.1所示,SWT由三个基本组件组成:一个本地库,负责与操作系统通讯;一个显示类,作为SWT与GUI平台通讯的接口;一个Shell类,作为程序的顶层窗口,可以容纳窗口小部件(Widget)(控件组件的另一种说法)。

图D.1 SWT窗口小部件间及与底层操作系统间如何相互适应


  在我们继续之前,让我们来研究一下我们刚刚引入的一些术语:
  • 显示(Display)--想象显示类的最好方式是把它当作一位管家。它执行所有重要的任务而使得你不必去管他们。这个类所做的最重要的工作之一是将本地平台事件和适宜在SWT中使用的那些进行互译。在你开发自己的程序的时候,你通常不需要对显示类做些什么,只需在创建其他所有窗口前先创建它。
  • Shell--从根本上说,一个用户看到的窗口是被操作系统的窗口管理器最终控制的。Shell被用作两种不同类型的窗体。第一种是你的程序的顶层窗体,你的GUI的其它部分在其上构建。在这种情况下,Shell是作为显示类的子类来创建的。另一种类型是一个窗体是其他窗体的子窗体,比如对话框。这种情况下,该Shell作为其父窗体的那个Shell的子类。
  • 窗口小部件(Widget)--这个术语意指控件(Control)组件(Composite)。你会发现,在SWT文档的各处,这三个术语是交替使用的。简单说来,一个窗口小部件就是可以放置在其他窗口小部件中的一个GUI对象。
  • 控件(Control)--具有操作系统对应物的GUI项。例如,一个按钮,文本区域,或者菜单。
  • 组件(Composite)--一个可以拥有子窗口小部件的窗口小部件,比如工具栏和树。最好的例子是canvas,你可以利用它,在使用不同布局的各种子canvas的辅助下构造复杂的用户界面。
  SWT体系结构是设计来模拟平台程序结构的,所以它对于窗口小部件创建和资源清理有很重要的影响。
D.2.1 窗口小部件创建
  当你在SWT中创建一个控件的时候,你还需要考虑它是如何在底层操作系统中被创建的。每个控件都有一个相似的构造函数来接受两个参数:第一个指定其父窗口小部件,第二个指定此窗口小部件的样式。这对于许多操作系统的工作方式来说都是必要的。当该SWT对象被创建时,操作系统的对应对象也被创建了,而它需要知道自己的父对象是哪个。对于许多窗口小部件的样式设置来说也是一样的。一旦它们被创建了,其样式就不能修改了。(所谓样式就是一种有关窗口小部件外观的对操作系统的示意。比如,当你创建了一个按钮,样式就定义了其类型:单选按钮,普通按钮,复选按钮等等。)
D.2.2 资源清理
  通常,当你使用Swing(或AWT)的时候,你只需创建你的窗口小部件、图像、字体等等而无需关注它们的清理,因为你知道当垃圾回收器运行时JVM会处理它们的。然而,当你使用SWT时,你必须多加注意你对操作系统GUI资源的使用,因为只有有限的资源可用。
  当你在SWT中创建了一个基于资源的对象(例如颜色、鼠标指针、字体或图像)时,你必须清理它。如果你不清理那些你不再需要的东西,就会发生资源泄漏,而你会在这种状况下结束:不管是你的还是操作系统中运行着的其他程序,都将无法再创建任何对象。
  以下代码片段分配了一个颜色(Color)资源然后清理了它:

  Color blue = new Color (display, 0, 0, 255);
  blue.dispose();

D.3 SWT与事件


  你在所有SWT程序中都会看到的最常用的代码段如下:

  while (!shell.isDisposed ())
  {
    if (!display.readAndDispatch ())
    display.sleep ();
  }

  这通常被称为信息泵事件调度循环。它的工作是当顶层窗口打开时接收来自操作系统的事件(比如,用户在移动鼠标),把它们调度到合适的SWT窗口小部件中,然后休眠直至有其他事件需要处理。在你的程序中,你需要至少有一个这样的东西,否则你的程序将无法接收操作系统的任何事件,这会让用户不大高兴。
  这个方法和AWT和Swing所使用的很不一样,后者为开发者隐藏了这种机制。这在SWT中没有隐藏,因为如果你编写SWT代码并作为Eclipse插件的一部分,你根本不需要一个信息泵--你默认使用了由工作台提供的那个。
  剩余的事件处理机制和AWT和Swing所用的差不多。大量的基本事件类型以及它们各自的侦听器(Listener)、适配器(Adapter)都在包org.eclipse.swt.events中定义。参阅在线文档可以获得完整列表。以下代码段演示了如何创建一个事件侦听器以及如何将其加入到一个对象中:

  Button button = new Button(display, SWT.PUSH);
  button.addSelectionListener(new SelectListener()
  {
    public void widgetDefaultSelected( SelectionEvent e ) {}
    public void widgetSelected( SelectedEvent e )
    {
      System.out.println("Button Pressed");
    }
  });

  不熟悉事件处理的人不必担心,这很简单。如前所述,一个事件关联着一个诸如用户移动鼠标或者窗体被最大化之类的动作。对于每种可以接收的事件的类型,都有一个称为侦听器的接口。一个侦听器就是一个类,它知道如何处理特定事件并且还会做些有用的事情。要想创建一个侦听器类,你需要创建一个类来实现那个与你要处理的事件相符的特定的侦听器接口。
  观察前面的代码段可知,我们关注的是SelectionEvent,它在点击按钮时发出。如果你在Javadoc中查看该事件,你会看到正确的侦听器是SelectionListener。为了将一个侦听器添加到一个窗口小部件类,你调用它的一个addXXXListener()方法,正如前面代码中用到的addSelectionListener()

提示
与其花时间重复Javadoc中所说的东西,我们建议你查看在线帮助。在那里你可以找到一份关于可用事件类型的完整清单,并且还包括了它们以及处理(或生成)那些事件的窗口小部件的描述。要查看该帮助,选择[帮助]->[帮助内容]->[平台插件开发者指南]->[程序员指南]->[标准窗口小部件工具箱]->[窗口小部件]->[事件]。

D.4 SWT与线程


  当你使用SWT创建一个SWT程序时,要考虑的一个重要因素就是所有的窗口小部件是如何与线程交互的。如果你熟悉Swing和AWT编程,那么以下内容会比较熟悉,不过某些重要的差异还是需要注意的。
  一个被称为用户界面线程的单一的重要线程负责处理事件,调度它们到合适的窗口小部件,以及进行窗体描绘。没有了它,你的程序将无法做任何事情。你可能认为我们过去说过一些这方面的内容,我们的确曾经说过。
  在AWT和Swing中,用户界面线程或事件处理线程对开发者是隐藏的。而在SWT中,创建消息泵的线程就成了用户界面线程。这个设计决定使得要将SWT插件插入Eclipse中变得可能。与Sun的方法背离的另一点是,SWT的设计允许拥有多于一个的事件调度线程。(这个功能极少用到,我们提到它只是为了完整起见。)
  主线程就是用户界面线程,所以你不该执行任何复杂的或耗时的任务(如数据库访问)或者其他会阻塞线程的任务。相反的,你应该转到其他线程去执行那些操作。不这么做的话,将会严重影响你的用户界面的响应能力并且会给用户带来不便,这永远不是件好事。与此相关的事实就是,唯一允许调用SWT窗口小部件而不会引发SWTException异常的线程就是用户界面线程。
  你也许想知道在你转到的线程完成之后如何更新用户界面。要做到这样,你要使用两个辅助方法,它们是显示类(Display)的一部分:asyncExec()syncExec()。(Swing用户注意:这些方法和Swing工具包类中的invokeLater()invokeAndWait()方法同义。并且,是的,如果你觉得Sun的方法的命名更为清晰,我们赞同。)这些方法按以下方式工作:
  • asyncExec(Runnable)--当你需要更新用户界面但并不关心具体何时更新时使用。记住,使用此方法意味着后台线程和用户界面间的处理不存在任何可保证的关联。
  • syncExec(Runnable)--当你的背景线程需要先进行用户界面更新才能继续处理时使用。注意,在用户界面更新进行之前,你的背景线程会被阻塞。
  这些方法都采取了实现Runnable接口的类。以下代码显示了你一般会如何使用这些方法:

  Display.getDefault().asyncExec(new Runnable()
  {
    public void run()
    {
      button.setText(new Date().toString());
    }
  });

  asyncExec()方法是显示类的一部分,所以你首先需要取得显示类的当前实例,这样做就避免了在你的整个程序中传递显示类的引用。你将一个实现了Runnable接口的类传递到asyncExec()方法。通常你创建一个匿名类来进行更新,正如前面的例子所示。

D.5 构建和运行SWT程序


  你可能想要开始编程了,或者至少也要看一些正确的SWT代码--很快我们就要这么做。然而,在那之前,让我们来告诉你如何构建和运行代码。
  这本书是有关Eclipse的使用的,所以我们首先关注配置Eclipse以使你能进行SWT开发。然后我们来看看需要什么来运行代码。最后,我们会解释从命令行运行你的SWT程序时的步骤。
  要配置Eclipse,请按如下步骤进行:
  1. 在[工作空间]视图中选择你的项目,选择右键菜单中的[属性]。
  2. 选择[Java构建路径],然后点击[[库]]标签页。
  3. 选择[添加外部Jar]。注意,如果你很可能要经常使用SWT,你可能会想要创建一个变量。
  4. 定位到适合你的平台的swt.jar文件,如图D.2所示(<eclipse-root>就是Eclipse所在的目录):
    • Linux GTK --<eclipse-root>/plugins/org.eclipse.swt.gtk_2.1.0/os/linux/x86
    • Linux Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/linux/x86
    • Solaris Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/solaris/sparc
    • AIX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/aix/ppc
    • HPUX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/hpux/PA_RISC
    • Photon QNX --<eclipse-root>/plugins/org.eclipse.swt.photon_2.1.0/os/qnx/x86
    • Mac OSX --<eclipse-root>/plugins/org.eclipse.swt.carbon_2.1.0/os/macosx/ppc
  5. 点击[确定]。
图D.2 通过项目[属性]对话框来添加swt.jar到你的classpath中。你可以使用[添加外部JAR]按钮或者[添加变量]选项来定位它。


注意
对于某些平台,比如GTK,需要不只一个的JAR来运行SWT(GTK使用文件swt.jar和swt-pi.jar)。在这种情况下,你必须添加所有需要的JAR到classpath中。要这样做,请对每个JAR文件重复以上步骤。所有的JAR文件都定义在同一个目录(文件夹)中。

  要运行你的代码,你需要按以下步骤进行:
  1. 在[工作空间]视图中,选择你要运行的包含有main的那个类。
  2. 选择[运行]->[运行...]。
  3. 在[运行]对话框中,选择[Java Application]并点击[新建]。
  4. 选择[自变量]标签页,并在[VM自变量]文本框中点击鼠标。
  5. 输入-Djava.library.path=<path>,其中<path>依据你的操作系统而定,是如下之一(如图D.3所示):
    • Win32 --<eclipse-root>\plugins\org.eclipse.swt.win32_2.1.0\os\win32\x86
    • Linux GTK --<eclipse-root>/plugins/org.eclipse.swt.gtk_2.1.0/os/linux/x86
    • Linux Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/linux/x86
    • Solaris Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/solaris/sparc
    • AIX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/aix/ppc
    • HPUX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/hpux/PA_RISC
    • Photon QNX --<eclipse-root>/plugins/org.eclipse.swt.photon_2.1.0/os/qnx/x86
    • Mac OSX --<eclipse-root>/plugins/org.eclipse.swt.carbon_2.1.0/os/macosx/ppc
  6. 点击[应用]然后点击[调试]。
图D.3 要让你的程序找到本地SWT的DLL,你需要通过[运行]对话框来把它加入到你的Java库路径中。


  你的程序现在运行了。记得中止示例。要这么做,你可以点击[控制台]视图的小方块。
  从命令行运行你的代码也差不多:
  1. 确保适合你的平台的JAR文件在classpath中。
  2. 调用java并带上-Djava.library.path参数(如前面的步骤所述)以及你的程序名。

D.6 使用SWT


  我们已经讲述了SWT的概念以及如何设置Eclipse以构建及运行示例。现在是看看简单的SWT示例的时候了。
  我们会带领你一起浏览组成示例的各个类,而不是将这些代码一下子灌给你。如果你想用Eclipse来照做,确认Eclipse已经按照D.5节描述的步骤设置过了。然后,创建两个Java类(文件->新建->类):BasicFrameworkMainApp。确认你建有包org.eclipseguide.swt,并是在其中创建它们的。
D.6.1 BasicFramework类
  让我们首先来看看BasicFramework。第一个部分定义了该类所在的包,然后导入了示例所需的类:

  package org.eclipseguide.swt;
  
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.*;
  import org.eclipse.swt.widgets.*;

  BasicFramework定义为抽象类以确保该类的所有子类都提供dispose()和displayHelpAboutDialog()方法的实现。在这个基础框架中,这些方法作为提醒来使用,以便你记得要清理资源以及要提供你自己的[关于]对话框。
  代码的其它部分是你很快就要用到的窗口小部件的声明:

  public abstract class BasicFramework
  {
    protected Display display;
    protected Shell shell;
    protected Menu menuBar, fileSubMenu, helpSubMenu;
    protected MenuItem fileSubMenuHeader;
    protected MenuItem fileExit, helpSubMenuHeader;
    protected MenuItem helpAbout;
    public abstract void dispose();
    public abstract void displayHelpAboutDialog();

  下面的内部类实现了SelectionListener以便处理选择事件。它会被连接到[退出]菜单项(很快就定义)。主要做的是关闭窗体,也就是中止消息泵,然后调用dispose()以确保两个动作衔接在一起:

    class FileExitListener implements SelectionListener
    {
      public void widgetSelected(SelectionEvent event)
      {
        shell.close();
        dispose();
      }
      public void widgetDefaultSelected(SelectionEvent event)
      {
        shell.close(); dispose();
      }
    }

  类似的,下一个内部类处理[帮助]菜单的[关于...]按钮的选择事件:

    class HelpAboutListener implements SelectionListener
    {
      public void widgetSelected(SelectionEvent event)
      {
        displayHelpAboutDialog();       }
      public void widgetDefaultSelected(SelectionEvent event)
      {
        displayHelpAboutDialog();
      }
    }

注意
在这两个侦听器类中,widgetSelectedwidgetDefaultSelected这两个方法处理的事件类型不同。widgetSelected处理用户用鼠标选择窗口小部件的事件,例如,点击一个按钮。widgetDefaultSelected处理当按钮具有焦点时,用户按[空格]键或[回车]键所产生的事件。

  下面你要开始建立SWT体系结构的层次结构:

    public BasicFramework(String windowTitle)
    {
      display = new Display();
      shell = new Shell(display);
      shell.setText(windowTitle);

  记住,Display窗口小部件是你的程序与操作系统对话的中转对象。随即创建Shell并传递display给它作为其父部件。该Shell就作为你的顶层窗体,其他所有东西都在其上建立。最后,Shell有一系列的辅助方法:setMinimized()setMaximized()、等等。在这里,你设置了窗口标题。
  在SWT中创建一个全功能菜单栏是一个复杂的过程。设计者不是只提供一些简单的类诸如菜单栏、菜单、菜单项、子菜单,而是采用了两个类,并依据所传递的样式来充当不同的角色:

      menuBar = new Menu(shell, SWT.BAR);
      fileSubMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
      fileSubMenuHeader.setText("文件(&F)");

  第一步是创建菜单栏以供其他所有菜单挂载。你可以通过传递样式参数SWT.BAR来实现。然后要创建一个挂载点,基本上就是个供菜单挂载的占位符。最后是设置该占位符显示在菜单栏上的文字。字母“F”旁的“&”号表明将“F”作为助记符(访问该菜单的一个键盘快捷键)。使用时,可以按[Alt]键激活菜单然后按[F]键来选择该菜单。然后就可以使用光标键来浏览菜单了。
  菜单创建工作的下一部分要求你创建在点击文字[文件]时显示的菜单。通过指定DROP_DOWN样式来把它创建为下拉菜单。(另一个可用选项是POP_UP,这将会建立弹出菜单,在右键点击选择或其它方式中很有用。)然后,把菜单连接到占位符:

      fileSubMenu = new Menu(shell, SWT.DROP_DOWN);
      fileSubMenuHeader.setMenu(fileSubMenu);

  在创建菜单的最后阶段里,你要创建菜单的项目。就像过去一样,你需要指定菜单项的样式,不过你有更多的选择--除了创建一个普通按钮式菜单项,你还可以创建复选项目、单选项目,或者是一个分隔条(用来给你的菜单分段):

      fileExit = new MenuItem(fileSubMenu, SWT.PUSH);
      fileExit.setText("退出(&X)");

  这些和[文件]菜单的写法一样:

      helpSubMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
      helpSubMenuHeader.setText("帮助(&H)");
      helpSubMenu = new Menu(shell, SWT.DROP_DOWN);
      helpSubMenuHeader.setMenu(helpSubMenu);
      helpAbout = new MenuItem(helpSubMenu, SWT.PUSH);
      helpAbout.setText("关于(&A)");

  下面就要把侦听器类连接到菜单项了。从这里开始,当你点击[文件]菜单的[退出]项或者[帮助]菜单的[关于]项时,这些事件就会被处理:

      fileExit.addSelectionListener(new FileExitListener());
      helpAbout.addSelectionListener(new HelpAboutListener());

  下面一行将菜单栏连接到顶层的shell

      shell.setMenuBar(menuBar);
    }

  以下是BasicFramework类的最后一段代码。这段很重要,它不仅使顶层窗体(Shell)显示在屏幕上,还创建了消息泵--这个示例的核心。当你开发独立运行的程序时,记住,没有了这一部分,你的程序所能做的将非常有限:

    public void mainLoop(int hSize, int vSize)
    {
      shell.setSize(hSize, vSize);
      shell.setVisible(true);
      shell.open();
      while (!shell.isDisposed())
      {
        if (!display.readAndDispatch())
          display.sleep();
      }
    }
  }

D.6.2 MainApp类
  现在,我们来看看MainApp类,它扩展了BasicFramework类并做了些很有用的工作。像以往一样,你要将这个类声明为org.eclipseguide.swt包的成员,然后导入示例需要的所有类:

  package org.eclipseguide.swt;

  import java.util.*;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.*;
  import org.eclipse.swt.layout.FillLayout;
  import org.eclipse.swt.widgets.*;

  要设置一个计时器,你要使用java.util.Timer类而不是使用一个线程。如果你没用过Java 1.3及以上版本(1.3版是Eclipse运行的最低要求),你可能没用过这个类。这是一个简单便捷的类,它提供了一个专用的计时器线程:

  public class MainApp extends BasicFramework
  {
    Timer timer;
    Button button;

  这个按钮放置在程序的主窗体中并显示时间。当点击按钮时,它会将时间打印到控制台。
  下面的内部类扩展了抽象类TimerTask。基本上,一个计时器任务就是一个传递到计时器的Runnable,它会以指定间隔执行。在run方法中,你要将一个匿名的runnable增加到事件队列里,以便用当前时间来更新按钮文本。由于并不关心用户界面线程什么时候会处理它,所以要用asyncExec方法来加上它:

    private class ClockUpdateTask extends TimerTask
    {
      public void run()
      {
        Display.getDefault().asyncExec(new Runnable()
        {
          public void run()
          {
            button.setText(new Date().toString());
          }
        });
      }
    }

  这是MainApp类的构造函数。在这里要调用其父类BasicFramework的构造函数并传递标题文字:

    public MainApp()
    {
      super("SWT Example Framework");

  每个窗体都可以有一个布局管理器以控制窗口小部件的位置和大小:

      shell.setLayout(new FillLayout(SWT.VERTICAL));

  有5种已定义好的布局:填充布局(FillLayout)堆布局(StackLayout)网格布局(GridLayout)表单布局(FormLayout)以及行布局(RowLayout)。同时还有一个自定义布局(CustomLayout)供你更好的控制窗口小部件的位置。

提示
如果要获得更多关于布局的信息,我们建议你阅读文章“了解SWT中的布局”(Eclipse站点的文章区载有此文:http://www.eclipse.org/articles/)。

  代码的下一部分创建了一个普通按钮并将它加到了shell窗口上。你目前正在使用填充布局,所以无法设置按钮大小。它只会简单的扩展到全部可用的空间中:

      button = new Button(shell, SWT.PUSH);

  以下代码展示了将一个侦听器连接到一个窗口小部件的另一途径--将其与一个匿名类连接。对于短小的类来说,应该优先使用匿名类。 除外,建议使用完全类(作为内部类或者友好包):

      button.addSelectionListener(new SelectionListener()
      {
        public void widgetSelected(SelectionEvent event)
        {
          System.out.println( "Button clicked - time is: " + button.getText());
        }
        public void widgetDefaultSelected(SelectionEvent event)
        {
          System.out.println( "Button pressed with default key - time is: " + button.getText());
        }
      });

  下面就要创建定时器并安排你的ClockUpdate任务了,它将在0毫秒的延迟后启动,之后每隔1000毫秒(1秒)调用一次:

      timer = new Timer();
      timer.scheduleAtFixedRate(new ClockUpdateTask(), 0, 1000);

  你不需要告诉计时器开始工作--程序一创建,它就立即运行了。
  以下代码调用了BasicFramework类的mainloop,在那里会进入事件循环直至shell被关闭。那时,就将会退出程序所运行的JVM:

      this.mainLoop(300, 200);
      System.exit(0);
    }

  这些代码创建MainApp类并开始整个程序的运行:

    public static void main(String[] args)
    {
      new MainApp();
    }

  现在你就要实现父类的抽象方法了,然而,这些代码没有用它们来做任何有用的事情。这种设计是为了让你能把所有声明过的资源都放入dispose方法中,以便轻松定位所有需要清理的资源:

    public void dispose()
    {
      System.out.println("Disposing of Resources");
    }
    public void displayHelpAboutDialog()
    {
      System.out.println("Display Help About Dialog");
    }
  }

  我们同样想象到,你会把创建你的[关于]窗体所需的一切东西放进displayHelpAboutDialog()方法中。
D.6.3 试验示例
  代码完成后,你就可以运行一下来试试看了。如果你完全照做的话,示例看起来会是图D.4的样子。

图D.4 SWT示例,演示了菜单、按钮以及文字。点击按钮会写入一行到控制台中。

<< Eclipse In Actio... / Eclipse In Actio... >>

专题推荐

不平凡的水果世界

不平凡的水果世界

平凡的水果世界,平凡中的不平凡。 今朝看水果是水果 ,看水果还是水果 ,看水果已不是水果。这境界,谁人可比?在不平凡的水果世界里,仁者见仁,智者见智。

中国春节的那些习俗

中国春节的那些习俗

正月是农历新年的开始,人们往往将它看作是新的一年年运好坏的兆示期。所以,过年的时候“禁忌”特别多。当然,各个地方的风俗习惯不一样,过年的禁忌也是不一样的。

评论
0/200
表情 验证码:

Addone
  • 文章总数0
  • 画报总数0
  • 画报点击数0
  • 文章点击数0
  • 个人排行
          博文分类
          日期归档