第二节 问候JFace的世界
HelloWorld程序又一次向世界问候了,不过这一次是用JFace。因为JFace添加了一些Java库(但是并没有本地库——记住它是建立在SWT之上的),你需要一个新的Ant文件(见清单13-1)去生成和运行这个程序。
清单13-1: build.xml
<project name="GenericJFaceApplication" default="run" basedir=".">
<description>
Generic JFace Application build and execution file
</description>
<property name="main.class" value=""/>
<property name="src" location="."/>
<property name="build" location="."/>
<!-根据你的Eclipse主目录更新location的值 -->
<property name="ecl.home" location="c:\eclipse"/>
<!-根据你的窗口系统(win32、gtk、motif等等)更新value的值 -->
<property name="win.sys" value="win32"/>
<!-根据你的操作系统(win32、linux等等)更新value的值 -->
<property name="os.sys" value="win32"/>
<!-根据你机器的体系结构更新value的值 -->
<property name="arch" value="x86"/>
<!-根据你的SWT版本更新value的值 -->
<property name="swt.ver" value="3.0.0"/>
<!-不要修改这行以下的代码 -->
<property name="swt.subdir"
location="${ecl.home}/plugins/org.eclipse.swt.${win.sys}_${swt.ver}"/>
<property name="swt.jar.lib" location="${swt.subdir}/ws/${win.sys}"/>
<property name="swt.jni.lib"
location="${swt.subdir}/os/${os.sys}/${arch}"/>
<property name="runtime.jar.lib"
location="${ecl.home}/plugins/org.eclipse.core.runtime_${swt.ver}"/>
<property name="jface.jar.lib"
location="${ecl.home}/plugins/org.eclipse.jface_${swt.ver}"/>
<property name="osgi.jar.lib"
location="${ecl.home}/plugins/org.eclipse.osgi_${swt.ver}"/>
<property name="jfacetext.jar.lib"
location="${ecl.home}/plugins/org.eclipse.jface.text_${swt.ver}"/>
<property name="text.jar.lib"
location="${ecl.home}/plugins/org.eclipse.text_${swt.ver}"/>
<path id="project.class.path">
<pathelement path="${build}"/>
<fileset dir="${swt.jar.lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${runtime.jar.lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${jface.jar.lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${osgi.jar.lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${jfacetext.jar.lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${text.jar.lib}">
<include name="**/*.jar"/>
</fileset>
</path>
<target name="compile">
<javac srcdir="${src}" destdir="${build}">
<classpath refid="project.class.path"/>
</javac>
</target>
<target name="run" depends="compile">
<java classname="${main.class}" fork="true" failonerror="true">
<jvmarg value="-Djava.library.path=${swt.jni.lib}"/>
<classpath refid="project.class.path"/>
</java>
</target>
</project>
正如你所见,这个build.xml文件向classpath中添加了一些JFace的JAR文件。确保根据这个文件里的注释,按照你的操作系统、窗口系统等更新你的这个文件。如果你使用的是Eclipse,你可以添加这些JAR文件到项目属性页的Java Build Path这一部分。
清单13-2包含了HelloWorld的源代码。
清单13-2: HelloWorld.java
package examples.ch13; import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; /** * 你的第一个JFace应用程序 */ public class HelloWorld extends ApplicationWindow { /** * HelloWorld的构造函数 */ public HelloWorld() { super(null); } /** * 运行程序 */ public void run() { // 让open()方法在窗口被关闭之前都不返回 setBlockOnOpen(true); // 打开主窗口 open(); // 将display销毁 Display.getCurrent().dispose(); } /** * 创建主窗口的内容 * * @param parent 主窗口 * @return Control */ protected Control createContents(Composite parent) { // Create a Hello, World label Label label = new Label(parent, SWT.CENTER); label.setText("Hello, World"); return label; } /** * 程序的入口点 * * @param args 命令行参数 */ public static void main(String[] args) { new HelloWorld().run(); } }
像你对SWT程序所做的那样编译并运行HelloWorld:
ant -Dmain.class=examples.ch13.HelloWorld
在提示符下发出这个命令就可以看到如图13-1所示的窗口。
图13-1: JFace的HelloWorld
首先注意到的是HelloWorld类继承自一个ApplicationWindow类,这个类是JFace对Shell的抽象。当你在代码编辑器中敲入extends这个词的时候,SWT会让你觉得心虚,因为如此之多的SWT类(包括Shell)带有警告说它们并不是设计用来被继承的。别担心,继承一个ApplicationWindow类不仅是合法的,而且是提倡的用法。
接着,你找不到典型的SWT事件循环了:
Display display = new Display(); Shell shell = new Shell(); // 创建shell的内容 shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose();
取而代之的是一段更加简洁的代码:
setBlockOnOpen(true); open(); Display.getCurrent().dispose();
第一个方法调用,setBlockOnOpen(),设置了这样一个标记:当它为真的时候,告诉下一个方法,open(),进入一个和原先 SWT事件循环非常类似的事件循环。将true传给setBlockOnOpen()导致open()在窗口关闭之前不返回。然而当我们注意到第三个方法调用Display.getCurrent().dispose()的时候,JFace的优雅带来的愉悦稍许的淡了一些:你仍然需要销毁你所创建的。这是为了使用JFace带来的简单性而付出的一个小小的代价。
这个HelloWorld程序也没有显式的指定布局,因为默认的使用了一个叫做ApplicationWindowLayout的内部类来满足你所有的需求。它也不会显式的调用createContents()方法,而是依靠JFace框架去做。这里的代码比这本书里那些SWT的例子更加整洁,暴露更少的细节。