一个用于构建图形接口的图形化工具
David Gallardo
软件顾问
2004 年 5 月
与许多 Eclipse.org 项目类似,Visual Editor 项目的目标是构建一个用于构建工具(在这里是用于构建图形用户接口的工具)的工具。关于 Visual Editor 项目最有趣的事情是它已经发布了一个参考实现。Visual Editor 版本 0.5 是用于构建 AWT/Swing 应用程序的 GUI 构建器,这是一个期待已久的 Eclipse 特性。在很快就要发布的、预定在 2004 年中期提交的 1.0 版中,将增加对于 SWT 的支持。在本文中,您将获得关于 Visual Editor 及其背后技术的概览,以及 Visual Editor 0.5 用于构建 AWT/Swing 应用程序的特性的一个简短示范,以及关于 Visual Editor 1.0 中的 SWT 支持的预览。
Eclipse Visual Editor 项目介绍
仔细阅读关于 Eclipse 及其竞争者的优缺点的任何讨论线索,您将会发现关于各种特性的提示信息,这些特性在其中各方互有优劣,或者完全缺乏。直到最近,对于 Eclipse,似乎经常被提起的事情是它缺少 GUI 构建器:一个用于构建图形用户接口的图形化工具。值得高兴的是,通过 2003 年 11 月发起的 Eclipse Visual Editor 项目以及随后 Visual Editor 0.5 的迅速发布,这种情况已经得到弥补。Visual Editor 0.5 允许您通过一个完全的 WYSIWYG(所见即所得)图形化编辑器来创建 AWT/Swing 应用程序。
与 Eclipse 自身类似,Visual Editor 也基于 IBM 的代码贡献。熟悉 Websphere Studio Application Developer 5.x 中的 Visual Editor 的开发人员将会发现 Eclipse 的 Visual Editor 几乎与之完全相同。要想了解如何使用 Visual Editor,请参阅 Websphere Studio Visual Editor 文档,该文档在本文末尾的 参考资料一节中列出。
与 Eclipse.org 组织下的许多其他项目(包括 Eclipse)类似,Visual Editor 项目所确定的目标是非常宏伟的:构建一个用于构建图形化编辑工具的工具。尽管最初发行版中对于 AWT/Swing 的支持已经完成,但是 Visual Editor 的计划远不止于此。技术基础正在进行重新设计,从而使得它对于编程语言和所支持的图形工具集来说是不相关的。
在将来,您会看到除了 AWT/Swing 以外的其他的 Visual Editor 实现(比如 SWT),以及潜在的除了 Java 语言以外的其他语言的实现(比如 C++)。有关增加 SWT 支持的工作已经在进行之中,事实上,这将会包括在 Visual Editor 版本 1.0 中,预定在 2004 年中期,大概与 Eclipse 3.0 同期完成。
Visual Editor 的内幕
Visual Editor 的第一个具体实现,作为一个针对 AWT/Swing 的 GUI 构建器,对于 GUI 开发人员来说已经是足够令人满意的了,但是如果您是那种希望了解内幕的开发人员,那么还可以看到许多东西:Visual Editor 利用一些非常有趣的技术,这些技术本身都是有用的。如果您对于构建自己的图形化编辑器或者对工具建模感兴趣的话,那么现有的 Visual Editor 实现对于您可以完成的事物来说只是一个线索。
Visual Editor 所利用的最为明显的工具是 GEF,即图形化编辑框架(Graphical Editing Framework)。GEF 建立于本地 Eclipse 图形化工具集 SWT 之上,以使得开发一个图形化编辑器或者所见即所得文本编辑器更为容易。如果您熟悉 SWT (或者 AWT/Swing,在这方面它们是类似的)中的图形原语,那么您会知道绘制和处理任意的形状(比如矩形、箭头和椭圆)是比较困难的,更不用说管理它们之间的关系以及它们所代表的数据模型了。
GEF 被划分为两个部分:第一部分是 Draw2D 插件,这是一个轻量级的绘图和呈现包,用于帮助您绘制图形。第二部分是 GEF 插件,除了其他工具以外,这一部分中还增加了选择和创建工具、工具选项板,以及用于在数据模型和视图之间进行映射的控制器框架。
GEF 是一个模型无关的框架,但是作为 Visual Editor (以及其他生成代码的图形化工具)的一部分,它在后台使用 Eclipse 建模框架(Eclipse Modeling Framework, EMF),以在模型、Java 类和图形化表示之间进行映射,其中模型是使用 XML 元数据交换(XML Metadata Interchange, XMI)在内部存储的。EMF 的重要特性之一是它确保所有这些映射都是一对一的;所以尽管 XMI 可以被认为是模型的标准表示,但是在代码和图形之间来回切换并不会丢失任何信息。这就是为什么 Visual Editor 只需要保存模型的一种表示(即 Java 源代码),以及开发人员可以自由地在图形化编辑器之外编辑该源代码的原因。
要更多地了解 GEF 和 EMF,请参阅本文 参考资料小节中的链接。
利用 Visual Editor 开发 AWT/Swing 应用程序
正如前面所提到的,目前可用的版本 0.5 是一个完全的 AWT/Swing GUI 构建器。它与 Eclipse 2.1.x 共同工作,并且与其他 IDE 中的 GUI 构建器相比毫不逊色。首先,它生成高质量的代码,可以与一个有经验的 GUI 开发人员通过手工开发的代码相媲美,并且不带有使得修改变得困难的特殊工件(artifact)。其次,它强大的分析能力允许完全的代码来回转换,因此对源代码的修改几乎立即反映在图形化编辑器中。
在手工构建 Swing 应用程序时,最为乏味的任务之一就是使用布局管理器来管理组件的位置。因为 Visual Editor 是一个所见即所得图形化编辑器,所以利用它很容易在用户接口中获得您想要的外观和行为。而且,因为它可以在不同的布局管理器之间自动映射,所以您可以使用一个 null 布局来创建您的应用程序外观,然后切换到一个栅格单元(grid-bag)布局。使用 null 布局能够容易地准确获取您想要的布局,栅格单元布局则允许布局在窗口尺寸改变时能够运行良好。
在下面几节中,我们将快速地浏览 Visual Editor 0.5 以及它的一些最有趣的特性。如果您想随同实践的话,需要安装 Eclipse 2.1.x 和 Visual Editor 0.5。而且,Visual Editor 还需要另外两个插件,即 EMF 和 GEF。关于下载链接和安装信息,请参阅 参考资料小节。
Visual Editor 工具
在安装完 Visual Editor 之后,下次创建新的 Java 项目时,您将会发现一些新的特性。假设您已经创建了一个名为 VEPExample 的项目。如果在 Package Explorer 中右击该项目名并且从上下文菜单中选择 New,您将会看见一个新的用于创建 Visual Class 的选项。单击该选项将弹出一个熟悉的对话框,但是具有新的名字:“Create a new Java Class using the Visual Editor”。您还会注意到的另一个差别是有多个单选按钮和一个用于选择父类的复选框。一般情况下,您将创建一个 JPanel 来包含应用程序的 UI 元素,然后将该面板添加到 JFrame。为了简短起见,这里将创建一个框架并且直接向它添加元素。关于开发 Swing 应用程序的更多信息,请参阅 参考资料小节中列出的系列教程。
为该类输入一个名字,比如 Test
,并且确保在“Which visual class would you like to extend?”区域中选中“frame”和“swing”。另外,还在“Which method stubs would you like to create?”下选中 main()
(如图 1 所示)。
图 1. 创建新的可视类
选择完之后,按 Finish创建可视类并使用 Visual Editor 打开它。您将会注意到,与常规的 Java 编辑器不同,Visual Editor 具有三个不同的部分。顶部是一个图形化编辑器,其中显示您的可视类在运行时的可能形状。左边是窗口部件的一个列表,这些窗口部件可以被拖放到您的应用程序中。底部是源代码(见图 2)。
图 2. 利用 Visual Editor 编辑 Swing 类
通过向下滚动源代码并找到 initialize()
方法,您可以看到源代码和图形化视图之间的交互 initialize()
。 方法用于设置应用程序窗口的初始尺寸:
private void initialize() {
this.setSize(300, 200);
this.setContentPane(getJContentPane());
}
|
如果将第一个数字(即宽度)改变为一个新值,比如 600,您将看到上面的图形化表示马上会改变宽度以反映这个新值。如果您在做大量源代码的改动,那么可以单击 Eclipse 状态栏中的 Stop Round Tripping按钮来关闭同步;否则,编辑器有可能会变得没有您所希望的那样反应迅速。
除了 Visual Editor 之外,您会注意到 Java 透视图中还有两个新的视图:位于左下部的 Java Beans 视图和位于右上部的 Properties 视图。您可能知道,Swing 的设计特性之一是,每个组件,比如您刚才创建的框架类以及添加到它之上的任何其他窗口部件,都是一个 Java Bean。Java Beans 视图允许您容易地在类中导航到这些组件。最初,在“this”(指当前在 Visual Editor 中的类)之下的惟一入口是 jContentPanel。您可能知道,并不直接向 JFrame 添加组件,而是将组件添加到它的内容面板。单击 jContentPanel 将指向框架类中的 getJContentPanel()
方法(见图 3)。
图 3. Java Beans 视图
Visual Editor 所增加的另一个视图是 Properties 视图,它显示一个 Java Bean 的属性。在这里,例如在 JavaBeans 视图中选择 jContentPane 之后,您可以改变它所使用的布局管理器。(在这样做之前,您可能希望在 Editor 窗口中浏览一下源代码,查看它是通过调用带有一个 java.awt.BorderLayout
对象的 jContentPane.setLayout()
方法来设置布局管理器的。) 一些属性允许您随意地输入文本,但是其他属性则提供一个更为合适的接口;针对布局管理的属性使用一个下拉列表,使您只能在有效的布局管理器中进行选择。单击缺省值 BorderLAyout,然后向上滚动所显示的列表并选择 null 布局管理器(见图 4)。
图 4. 选择 null 布局管理器
在做出该改动之后,您将看到在源代码中, jContentPane.setLayout()
现在通过一个 null 值被调用。如果您希望自己证实 Properties 视图和 Editor 之间的交互在两个方向上都能够工作,您可以尝试在源代码中将 null 改回为新的 java.awt.BorderLayout()
,并且确认在 Properties 视图中该值自动改变。
创建和启用用户接口
一旦已经为您的应用程序创建了一个框架,就可以开始添加窗口部件以允许用户与您的应用程序进行交互。让我们添加一个复选框用于开关消息。首先,单击 JCheckbox 窗口部件,然后在图形化编辑器中的框架内单击。如果您使用的是 null 布局管理器,您会注意到可以将它放置在内容面板的任何地方;如果您使用的是 BorderLayout,您可以选择将它放置在北部、南部、东部、西部或者中部。
接着,单击 JLabel 窗口部件并在前面所添加的复选框中单击 Next。使用 Properties 视图,将文本改为“Unchecked”,然后调整文本框的尺寸使得文本能够恰好适中。(另一个方法是,首先扩展该框然后单击左上角;这将打开一个文本域,在这里您可以键入文本。)
现在,如果您愿意的话,可以使用调整工具(alignment tool)来整理窗口部件。通过按下 Control 键并且依次单击每个组件来选择它们,然后单击 Show Alignment Window按钮和 Align Top按钮,如图 5 所示。
图 5. 使用调整工具来对齐组件
现在,您的框架看起来应该类似于图 6 所示。
图 6. 具有两个窗口部件的框架
如果您现在开始运行该应用程序,当然不会发生太多的事情。您可以将该复选框单击为打开或者关闭,因为 Swing 会为您负责这件事情,但是要想让它实际做某些事情,您还需要添加一些代码。如果熟悉 Swing 事件模型,您就知道需要为复选框添加一个活动监听器,从而每当用户改变它时,监听器都可以执行某个动作。要使用 Visual Editor 添加一个监听器,可在图形化编辑器中右击该复选框,并且从显示的上下文菜单中选择 Events > Action Performed。这将把实现为匿名类的活动监听器的代码添加到复选框的初始化代码中:
private javax.swing.JCheckBox getJCheckBox() {
if (jCheckBox == null) {
jCheckBox = new javax.swing.JCheckBox();
jCheckBox.setBounds(45, 75, 21, 21);
jCheckBox
.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.out.println("actionPerformed()");
// TODO Auto-generated Event stub actionPerformed()
}
});
}
return jCheckBox;
}
|
您可以看到,在需要添加代码的地方已经利用一个 TODO 注释进行标识。让我们改动代码,以便每当复选框发生变化时,它旁边的标签也会发生变化以反映该复选框的状态。在您做出改动之后,新的代码看起来应该是这样的:
jCheckBox
.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
jLabel.setText(
jCheckBox.isSelected() ? "Checked" : "Unchecked");
}
});
|
现在到了测试应用程序的时候了。
运行 Visual Class
Visual Editor 可以让您方便地启动 Java Bean,而不需要一个 main()
类。当您正在测试一个组件(比如 JPanel),而该组件与最终将要包含它的应用程序相分离的时候,这会特别方便。要以这种方式启动您创建的简单测试应用程序,请确保在 Editor 中已经选中 Test.java
,然后从 Eclipse 主菜单中选择 Run > Run As > Java Bean。
另一个方法是,由于这是一个 JFrame,您还可以通过像下面这样完成 main()
方法,来将 Test 作为一个 Java 应用程序运行:
public static void main(String[] args) {
Test test = new Test();
test.setDefaultCloseOperation(EXIT_ON_CLOSE);
test.setVisible(true);
}
|
从主菜单中选择 Run > Run As > Java Application来运行它。无论以哪种方式运行它,您都应该看到,每当单击该复选框时,标签就会相应地发生变化。
如果您并没有在 Eclipse 中跟着实践,但是希望看到代码的样子,您可以使用 参考资料中提供的链接下载它。
了解 Visual Editor 1.0 中的 SWT 支持
在撰写本文的时候,Visual Editor 1.0 的初步版本(preliminary build)提供对于 SWT 支持的预览,尽管最终的版本有可能是不同的。这里我们将快速地来了解一下,但是注意如果您使用的是一个更新的版本,您可能需要做出调整。
当您下载一个非发布版本(non-release build)的 Visual Editor 1.0 时,例如我们这里所使用的 I20040325 集成版本(integration build),则还需要下载相应的 Eclipse、EMF 和 GEG 版本(build)。这些并不一定要是发布版本(release build),并且您不能混合和匹配版本。VEP 下载页面(请参阅 参考资料)将指定需要哪些版本并且包含指向这些版本的链接。
当安装完 Eclipse、Visual Editor、EMF 和 GEF 之后,启动 Eclipse,并创建一个新的 Java 项目。为了使用 SWT,您需要将 SWT 库添加到项目的 Java 构建路径。右击该项目并选择 Properties > Java Build Path。单击 Libraries 选项卡,单击 Add Library按钮,选中 Standard Widget Toolkit (SWT),然后单击 Next。在下一个对话框中,接受缺省的“Use Platform SWT Level”并单击 Finish。单击 OK关闭属性对话框。
与前面一样,通过右击该项目并选择 New > Visual Class来创建一个新的 Visual Class。为该类输入名字,比如 SWTTest
。然而,在这里并不选择“frame”作为要扩展的可视类,而是选择“other”。另外,还必须确保父类是 java.lang.Object
,并且在“Which method stubs would you like to create?”下面选中 main()
方法旁边的复选框(见图 7)。
图 7. 创建 SWT 可视类
开始,图形化编辑器的画布是空的。为了创建应用程序,您需要添加一个 SWT shell。您应该发现在 Visual Editor 左侧的窗口部件选项板中包含一个 SWT 窗口部件的选择项(除了 AWT 和 Swing 窗口部件之外)。单击 Shell,然后在画布上单击并拖动以创建应用程序窗口(见图 8)。
图 8. 将 SWT shell 添加到图形化编辑器
现在,您可以给 shell 添加窗口部件了。这里我只是添加单个文本域。单击 Text,然后在 shell 中单击并拖动以放置该文本域。单击该域的左上角以添加一些文本,比如“Hello, SWT!”。
图 9. Hello, SWT!
在完成这些步骤之后,您将发现 Visual Editor 已经创建了一个 createSSHell()
方法,该方法按照如下方式初始化 shell:
private void createSShell() {
sShell = new org.eclipse.swt.widgets.Shell();
text = new org.eclipse.swt.widgets.Text(sShell,
org.eclipse.swt.SWT.NONE);
sShell.setSize(new org.eclipse.swt.graphics.Point(209, 85));
text.setBounds(new org.eclipse.swt.graphics.Rectangle(23,
9, 153, 27));
text.setText("Hello, SWT!");
}
|
接着,我们需要向 main()
方法添加一些代码,以便实例化该类并且运行 SWT 代码:
public static void main(String[] args) {
SWTTest test = new SWTTest();
Display display = new Display();
test.createSShell();
test.sShell.open();
while (!test.sShell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
System.out.println("finishing...");
display.dispose();
}
|
在键入这些代码之后,您可以在源代码窗口中右击并选择 Source > Reorganize Imports,以解析对 Display 的引用。
为了运行该应用程序,您需要添加一个平台特定的 SWT 共享库或者 DLL 到您的路径。一种方式是使用启动配置。从 Eclipse 主菜单中选择 Run > Run...,然后在所显示的对话框中单击 Arguments 选项卡。在 VM arguments 框中,添加一个带有库路径的 -D 参数;在 Windows 中,如果您已经将 Eclipse 安装到 C:\eclipse
,那么完整的参数将是: -Djava.library.path=C:\eclipse\plugins\org.eclipse.swt.win32_3.0.0\os\win32\x86
。见图 10。
图 10. 将到 Windows SWT DLL 的路径添加到启动配置
在输入该参数之后,单击 Run启动 SWT 应用程序。如果一切都正确的话,应用程序窗口将打开并且带有“Hello, SWT!”消息,如图 11 所示。
图 11. “Hello, SWT!”应用程序窗口
结束语
Visual Editor 项目将期待已久的 GUI 构造器添加到 Eclipse。最初的 0.5 版本包括对于 AWT/Swing 的支持,在 GUI 开发方面它甚至使 Eclipse 与其他 IDE 具有同等的地位。下一个版本 1.0,预期很快就会推出并且将会包括热切期盼的 SWT 支持。除了这些之外,其他还是不确定的,但是由于它的可靠的技术基础,许多事情,包括对于其他编程语言和工具集的支持,都是有可能的。
参考资料
关于作者 David Gallardo 是 Studio B 的作者,他是一名独立软件顾问和作家,擅长于软件国际化、Java Web 应用程序和数据库开发。他成为专业软件工程师已经有 15 年多了,他拥有许多操作系统、编程语言和网络协议的经验。他最近在一家 B2B 电子商务公司 TradeAccess, Inc.从事先进的数据库和国际化开发。在这之前,他是 Lotus Development Corporation 国际产品开发部的高级工程师,负责开发,用于为 Lotus 产品(包括 Domino)提供 Unicode 和国际化语言支持的跨平台库。David 还与人合著了 Eclipse In Action: A Guide for Java Developers (Manning, 2003)。可以通过 david@gallardo.org 与他联系。 |
转自:
http://www-128.ibm.com/developerworks/cn/linux/opensource/os-ecvisual/