gui程序:创建本机、跨平台 GUI 应用程序

  本文举例源代码或素材下载

  众所周知Java 语言在服务器上以及 applet 领域已经非常成功了但是它在最终用户应用领域为什么没有大行其道呢?有几个原因首先即使很小应用内存占用通常也有好几兆字节第 2和 Java 语言起提供 GUI 库产生应用通常看起来和其本机同类应用区别因此无论您应用多么健壮或稳定和本机应用相比它都显得非常笨拙

  用于 Java GNU 编译器

  让我们从内存占用问题开始Java 应用要使用额外内存运行 Java 字节码时虚拟机必须完成许多“工作”在当今高级编译器中编译即时(just-in-time)发生并且编译器必须对这信息立即(on-the-fly)进行高速缓存Cache以供以后使用当然现在内存是便宜但是当有几个 Java 应用同时在台机器上运行时即使是大机器也可能由于持续内存页面调度而放慢速度进入用于 Java GNU 编译器(GCJ)GCJ 获得 Java 源代码或字节码然后将它们编译成本机机器代码然后可以将来自几个 Java 类机器代码链接在起成为单个本机应用

  月份Martyn Honeyford 为我们提供了本机编译和 GCJ 介绍(请参阅 参考资料以获取到 Martyn 文章链接)正如他通过举例向我们展示那样本机编译应用使用内存通常要比在虚拟机中运行应用要少得多

  标准窗口构件工具箱

  这很棒但是正如 Martyn 指出GCJ 尚不支持 AWT 或 Swing因此我们现在将如何建立本机编译 GUI 应用呢?进入标准窗口构件工具箱(SWT) API 是开放源码 Eclipse 工具平台部分为了避免引起 Swing 和 SWT 对抗(请参阅 参考资料以获取有关这场争论更多详细信息)让我介绍说明些 SWT 优势

  SWT 试图弥补 AWT 和 Swing 缺点使用 AWT我们将受到“最小公分母”限制:仅支持存在于所有平台上窗口构件 Mot 没有提供本机树型窗口构件而 Windows 提供了该功能AWT 就没有包含树型窗口构件

  Swing 走向了另个极端虽然带有个很出色 API 进行优雅地设计Swing 还是自己实现窗口构件因此 Swing 不依赖于操作系统提供窗口构件无论本机是否支持这都为 Swing 提供了不可思议灵活性但是 Swing 自己绘制这些窗口构件所以最终外观看起来和本机应用有明显区别

  SWT 试图弥合这两个 GUI 工具箱的间差距行军命令是:“如果有本机窗口构件就使用它如果没有就模拟它”前面提到树型窗口构件就是这样个举例 Windows 支持本机树型窗口构件所以在 Windows 上运行时SWT 就使用它但是Mot 不支持树型窗口构件因此 SWT 在 Mot 下运行时绘制其自己窗口构件版本使用 SWT结果应用看起来和其本机同类应用很相似尽可能地使用了本机窗口构件

  设置开发环境

  因此如何在本机编译所有这些应用呢?首先您需要个使用 GCJ 设置开发环境目前在 Linux 和其它 UNIX 变体(请参阅“Windows 上 GCJ”侧栏以了解 GCJ 在 Windows 上情况)上支持 GCJ设置开发环境最简便思路方法是安装种 Linux 分发版新近版本Mandrake 8.1 和 Red Hat 7.2 都带有需另外安装 GCJ 3.0.1 GCJ 仍然在发展所以可能想考虑使用最新和最好版本我选择在版本 3.0.3 和 3.0.4 上进行测试手工安装 GCJ 相对容易;GCJ 页面提供了相当好文档(请参阅 参考资料)

  旦有了个具有 GCJ 环境则下载 Eclipse SDK 并安装它这将为您提供 SWT 源代码和字节码要安装 Eclipse SDK请下载 ZIP 文件(在 Eclipse SDK 标题下)然后将它解压缩到个目录中我建议使用目录 /usr/local/eclipse但是任何目录都可以

  开始编译

  设置开发环境后就可以开始编译了编译应用包括对大多数 SWT 源代码执行和下面类似命令:

gcj -c MyClass.java -o MyClass.o

  大约有 30 个 SWT 源文件使用 Java 本机接口(Java Native Interface (JNI))因此我们需要以略微区别方式来编译它们(请注意 -fjni 标记):

gcj -fjni -c MyJNIClass.java -o MyJNIClass.o

  最后我们需要将结果对象编译成共享对象:

gcj -shared -o swt.so MyClass.o MyJNIClass.o ...

  构建 SWT

  在本文中我们将把 SWT 编译成共享对象然后在产生应用中动态引用这个对象请注意您可以使用应用代码将 SWT 编译成可执行文件但是基于本文所讨论范围我们将坚持编译成共享对象正如它名称所表明共享对象主要优点就是可以被共享在运行时所有应用都可以动态地使用同个对象产生可执行文件大小将小得多

  使用下载源代码中包含 Ant 构建文件(buildfile)我们将以自动方式编译 SWT这个文件完成两个主要任务首先它将几个补丁应用到 SWT 源代码(SWT 文件中有 3个将不能用 GCJ 进行编译这是些小编译器造成 ― 例如它不喜欢 x, y, x1, y1 作为行;必须将它们分成多行在这些情况下为这 3个源文件编写了小补丁以使它们在功能上等价正如我以前提到GCJ 仍然在发展;这些会逐渐消除)其次构建文件使用提供制作文件(makefile)来 make

  在清单 1 中显示 Ant 构建文件已经在 Ant 1.3 和 Ant 1.4.1 上测试过了请注意在清单中我除去了注释以节省空间但是有完整代码可供下载

  要运行构建请遵循下列步骤:

  安装 Ant(请参阅 参考资料以获取有关 Ant 更多信息)

  下载本文 源文件它包含构建文件、补丁和关联制作文件然后将它解压缩到个目录中

  导航至 SWT 目录然后输入 ant 构建文件假设您已经在 usr/local/eclipse 中安装了 Eclipse如果 Eclipse 安装在另个目录中请输入 ant -Declipse__dir=your_directory 其中 your_directory是您安装 Eclipse 目录

  注:如果不想使用 Ant 构建文件您可以手工解压缩 SWT 源文件和字节码然后使用 UNIX patch 命令来应用源代码中包含那 3个补丁(使用 .patch 文件)然后运行制作文件

  清单 1. Ant 构建文件

<project name="BuildEclipse" default="cleanup">
 <!--
 The following properties can be overridden at the command-line.
  e.g. ant -Declipse__dir=/usr/local/eclipse
 -->
 <property name="eclipse__dir" value="/usr/local/eclipse"/>
 <property name="temp_dir" value="build_temp"/>
 <property name="shared_object_name" value="swt.so"/>
 <target name="init">
  <mkdir dir="${temp_dir}"/>
 </target>
 <target name="unpack" depends="init">
  <unzip src="${eclipse__dir}/plugins/org.eclipse.swt/swtsrc.zip"
      dest="${temp_dir}"/>
  <unjar src="${eclipse__dir}/plugins/org.eclipse.swt/swt.jar"
      dest="${temp_dir}"/>
 </target>
 <target name="patch" depends="unpack">
  <patch patchfile="TabFolder.patch"
      originalfile="${temp_dir}/org/eclipse/swt/widgets/TabFolder.java"/>
  <patch patchfile="Widget.patch"
      originalfile="${temp_dir}/org/eclipse/swt/widgets/Widget.java"/>
  <patch patchfile="TreeEditor.patch"/>
  <move file="TreeEditor.java" todir="${temp_dir}/org/eclipse/swt/custom"/>
 </target>
 <target name="make" depends="patch">
  <execon executable="touch">
   <file dir="${temp_dir}" s="**/*.java" excludes="**/*."/>
  </execon>
  <execon executable="touch">
   <file dir="${temp_dir}" s="**/*." excludes="**/*.java"/>
  </execon>
  <copy file="Makefile" todir="${temp_dir}"/>
  <exec executable="make" dir="${temp_dir}">
   <arg line="-f Makefile"/>
  </exec>
 </target>
 <target name="cleanup" depends="make">
  <move file="${temp_dir}/${shared_object_name}" todir="."/>
  <delete dir="${temp_dir}"/>
 </target>
</project>


  创建应用

  既然您已经将 SWT 构建到共享对象中您就可以尝试样本应用显示在清单 2 中应用个显示经典“Hello, World!”消息简单窗口组成

  清单 2.“Hello, World”样本应用

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
public Hello {
  public void (String args) {
    Display display = Display;
    final Shell shell = Shell(display);
    RowLayout layout = RowLayout;
    layout.justy = true;
    layout.pack = true;
    shell.Layout(layout);
    shell.Text("Hello, World!");
    Label label = Label(shell, SWT.CENTER);
    label.Text("Hello, World!");
    shell.pack;
    shell.open ;
    while (!shell.isDisposed) {
       (!display.readAndDispatch) display.sleep ;
    }
    display.dispose


  要编译这个应用请遵循下列步骤:

  将 SWT 共享对象(swt.so)复制到 Hello World 目录中然后输入下列命令(请记住如果在 /usr/local/eclipse 以外目录中安装了 Eclipse SDK请用您目录来替换它)gcj -CLASSPATH=/usr/local/eclipse/plugins/org.eclipse.swt/swt.jar
 -c Hello.java -o Hello.o
gcj -=Hello -o Hello Hello.o swt.so




  接下来使用下列命令设置库路径(假设您正在使用 bash shell):export LD_LIBRARY_PATH=
 .:/usr/local/eclipse:/usr/local/eclipse/plugins/org.eclipse.swt/ws/mot


  输入 ./Hello 会看到本机编译 GUI Java 应用出现屏幕上!

  注:本文 源代码包括使这过程自动化制作文件

  展望

  对 Windows 应用编译很快就可以实现了(请参阅 Windows 上 GCJ侧栏)虽然目前仅在 Linux/Mot 和 Windows 上支持 SWT但正在进行积极开发以在 Linux 上将 SWT 移植到 GTK/GNOMESWT 还可以在 AIX 和 Solaris 上 Mot 下工作但是还未经全面测试最后在 Windows CE、QNX 和 Macosh 移植上已经完成了些工作但是目前主要侧重点还是针对其它平台

  结束语

  众所周知Java 语言具有些重要特性它是优雅提供了面向对象概念出色实现并且具有个非常有用标准类库将这些优点和 GCJ 和 SWT 相结合使 Java 语言定位成在服务器和 Web 浏览器上建立其基础然后转向最终用户应用领域



Tags:  .net跨平台 跨平台游戏 跨平台 gui程序

延伸阅读

最新评论

发表评论