利用 Rational Application Developer Visual Editor 实现 Swing 可视化组件与数据的绑定
引言
Java™可视化编辑器允许用户以图形化的方式编辑 Java 用户界面,
利用Rational Application Developer Visual Editor实现Sw
。在 IBM Rational Application Developer for WebSphere® Software V6 中,这一功能得到了进一步的增强。因为 V6 支持可视化组件与不 同来源的数据快速绑定,比如,这些数据可以来源于 Web 服务,也可以来源于 EJB 组件。这篇文章讲述了如何利用数据绑定的优秀特性,用一种快速而强大的 方法,来定义用户界面的数据读取和数据写入。Swing 概览
如同 许多其它部件一样,AWT(抽象窗口工具)和 Swing 图形界面组件均被包括在 JAVA 基础类库(JFC)中,它们提供了一个框架,可以轻松的构造图形用户界面 (GUI),为 JAVA 应用程序添加丰富的图形化功能性和互操作性。Swing 是一个 功能丰富的通用工具包,它提供了很多非常实用的功能。但出于我们的目标需要 ,在这里我们只集中描述两个重要的功能,因为这两个功能对于理解可视化编辑 器的绑定模型和绑定操作是最为重要的。
使用 Swing 的数据模型
大部分的 Swing 组件均有一些模型,利用这些模型,您可以灵活地决定 如何存储和检索应用程序中的数据。其中,在 Rational Application Developer(以下简称为Application Developer)的数据绑定工具中就有两个这 样的模型,它们是文档和表格模型,下面让我们看看这两个模型:
图 1 :文挡模型
在文档模型中(如图 1),使用文本组件从它的数据视图中分离出数 据(称为模型),该模型实现了 javax.swing.text.Document 接口,并提供以 下的服务:
包含文本。文档把文本内容存储在 javax.swing.text.Element 对象中,同时还可表示任意文本逻辑结构,比如段 落、共享样式文本等等。
通过 remove(String aString) 和 insertString(int position, String aString, AttributeSet anAttributeSet) 来提供对文本编辑的支持。
将文本的改动通知给文档 并使编辑 可撤销改动。
管理 Position 对象。当文本内容 被更改时,Position 对象会跟踪文本中的特定位置。
使您能够获取文本 的相关信息(例如它的长度),以及文本片段。
下面是在文本域中设置 一个文档的例子:
Document doc = new MyDocument();
...
textfield = new JTextField();
textfield.setDocument (doc);
图 2:表格模型
在表格模型中(图 2),图形化组件使您可以列出行和列的数据,同 时有滚动条来提供分页功能。每一个表格都从实现 javax.swing.table.TableModel 接口的对象中获取数据。通常,您可以将表格 模型作为 javax.swing.table.AbstractTableModel 类的子类来实现。
您的表格模型可以用 array、list、或 hash map 来存储数据,或者可以从外部 数据源(比如数据库)获取内容。在某些情况下,模型可以在执行期间实际生成 数据。
我们可以用 JTable 显示任意数据模型,并通过下面的代码来实 现 TableModel 接口:
TableModel myData = new MyTableModel ();
JTable table = new JTable();
table.setModel (myData);
使用 Swing 操作
当有两个或更多执行相同功能 的组件时,我们通常使用操作对象将功能封装起来,并实现 javax.swing.Action 接口。操作对象是一种操作 ,它提供操作--事件的 处理。使用 setAction 方法将操作添加到组件中,就会产生以下效果:
组件的状态被更新以匹配操作的状态。例如,如果设置了操作的文本和图标的值 ,组件的文本和图标就会更新,以反映这种变化。
在组件中,操作对象 被注册为操作
如果操作的状态发生改变,组件的状态会被更新以 匹配该操作。例如,如果您改变了操作的启用状态,所有与之关联的组件都会改 变各自的启用状态,以匹配操作的改变。
这里有一个为按钮设置操作的 例子:
Action myAction = new MyAction();
...
button = new JButton();
button.setAction (myAction);
Swing 可视化组件的数据绑定
Eclipse 中的 可视化编辑器使用 AWT/Swing 组件来支持可视化结构。设计选项板包含了常用 的组件、容器、菜单及控件,并使用可扩展、压缩和打开的 drawer 将它们组织 起来。
如果在绑定 Swing 可视化组件时不使用 Application Developer binder, 那么就是一种手动操作处理,这就要求我们在设计代码编辑器(design source editor)中加入正确的代码。然而,如果我们使用 binder,就可以使用数据源 、数据对象以及 Swing binder 助手类的组合,并利用可视化反馈,从而可以更 加快速、更加简便的进行可视化组件的数据绑定。
Application Developer 中支持的缺省 Swing 可视化组件包括文本域、表格 、按钮。如果需要,您还可以通过实现所提供的接口,为其它组件编写 binder 。Visual Editor 提供的对话框可以帮助您创建数据对象和数据源,您可以使用 它们来绑定可视化组件。然而,如果不使用这些对话框,您还可以通过选项板添 加基本数据对象、数据源数据对象及数据源,并使用 Properties 视图对它们进 行配置。考虑到将来可能要支持其它选件(widget)库,数据源和数据对象类均 完全独立于可视化组件。
当您将可视化组件绑定到数据源和数据对象时,binder 代码会根据需要被生 成到您的项目源文件目录中。在缺省情况下,所生成的类会被添加到项目的 jve.generated 包中。然后,您可以自由地扩展、替换、或重写数据绑定逻辑。 倘若您更改了 jve.generated 类并添加一些自定义的业务逻辑,它们将不会被 Visual Editor 改写。
Swing binder
Binder 将可视化组件连接到数据对象。可视化组件和它的 binder 之间是一 对一的关系。但数据对象和同它发生交互的 binder 之间则是一对多关系。换句 话说,就是可以将多个可视化组件绑定到一个给定的数据对象,但每个可视化组 件都需要它自己的 binder。
数据源
数据源如同数据工厂,它的目的是为数据对象提供数据,以及获取原始数据 。Application Developer 的可视化编辑器支持的数据源包括 J2EE 会话 bean 、Web 服务以及JavaBean。数据源可以看作是虚包(facade)工厂,它提供了各 种配置属性,从而可以实现数据源虚包的实例化和初始化。虚包是包含一套方法 的类,利用它,你可以从后台创建数据对象,或提供一些其它的业务功能。当然 ,这需要数据源实现者正确地实例化虚包。
数据对象
数据对象代表本地可用数据的对象。利用它,客户端组件可以进行交互;它 也是对象的封装器,可以管理该对象的属性变更事件。
图 3 显示的是 Application Developer 中的设计选项板,包括可视化组件 的 drawer,以及数据 binder。
图 3:Rational Application Developer 设计选项板
MyBooks 应用程序范例
这里,我们对 MyBooks 程序做了一些改动,以便我们能更好地关注 Application Developer visual editor for data binding 所支持的三个 Swing 可视化组件:JTextField、JTable 和 JButton。图 4 显示了 MyBooks 应用程序的一个屏幕截图,该程序将 XML 数据显示在 JTable 中,XML 文件名 显示在 JTextField 里,同时还有一个名为 SAVE 的 JButton。
图 4 MyBooks 应用程序表格模型
MyBooks 采用了一个参数:XML 文件的名称,它包含了所有在表格中显示的 书籍清单。当我们按下了 SAVE 按钮后,表格中的内容将被保存在文本域中指定 的 XML 文件里。
为了创建 MyBooks 应用程序,我们在 A 部分中设计好基本 GUI,然后在 B 部分中使用 Application Developer 可视化地将 GUI 与数据绑定起来。
A 部分:构建用户界面和 JAVA 数据工厂
为了构建 MyBooks 的用户界面,我们将使用可视化编辑器:
创建一个 JAVA 项目
在 Application Developer 中,选择 File => New => Project。
选择 Java Project 并按下 Next 按钮。
为项目输入名称 MyBooks ,然后按下 Next 按钮。
从 Application Developer 安装程序中将 xsdbeans.jar 添加到 Java 构建 路径中,这个 JVR 文件位于:
按下 Finish 按钮。
创建包 ve.eclipse 和 ve.rad。
添加主要的可视类
在 Package Explorer 中,右键单击项目并选择 New => Other。
选择 Visual Class 然后按下 Next 按钮。
指定压缩包的名称为 ve。
指定类的名称为 MyBooksApp。
确保超类 Superclass 是 javax.swing.JFrame,并且 public static void Main(String[] args) 被选中。
按下 Finish 按钮。
定制 JFrame
将私有变量 filename 添加到该类中,数据类型为 String。
修改构造函数 MyBooksApp() 的结构,使其如下所示:
public MyBooksApp(String f) {
super();
filename = f;
initialize();
}
修改 main(),使其如下所示: public static void main(String[] args) {
MyBooksApp app = new MyBooksApp(args[0]);
app.show();
}
在可视化编辑器窗口中选择文本 JFrame,并在弹出的可编辑文本框中,输入 MyBooks。
在可视化编辑器窗口中选择 JFrame. 组件,并确保当前处于 Properties 视 图。
从 Properties 视图中,将属性 defaultCloseOperation 设置为 EXIT,然 后按下 Enter 按钮。
从 Properties 视图中,将属性 size 设置为 400,200,然后按下 Enter 按 钮。
添加一个文本域
功能:这一可视化组件将显示 XML 文件名。
在选项板的 Swing Containers 部分中选择 JPanel。 然后把它拖放到可视 化编辑器中 JFrame. 组件之外的位置。
在选项板的 Swing Containers 部分中选择 JLabel,然后把它拖放到 JPanel 中。
从 Properties 视图中,将 JLabel 的 text 属性设为 XML filename:,然 后按下 Enter。
在选项板的 Swing Containers 部分中选择 JTextField,然后把它拖放到 JPanel 中。
将 JPanel 放置在 JFrame. 的 North 部分。
添加一个按钮
功能:这个可视化组件可以将表格中的数据保存到指定的 XML 文件中。
在选项板的 Swing Components 部分中选择 JButton,并将它放置在 JFrame. 的 South 部分。
从 Properties 视图中,将 JButton 的 text 属性设为 SAVE,然后按 Enter。
添加一个表格
功能:该可视化组件将显示 XML 文件的内容
在选项板的 Swing Containers 部分中,选择 JScrollPane 上的 JTable, 并把它放置到 JFrame. 的 Center 部分。
按下 CTRL-S 以保存可视类,然后关闭编辑器。
将类复制到 ve.eclipse 和 ve.rad 中。
这个练习的用户界面部分现在已经完成:我们创建了一个 JAVA 项目以存储 可视类 JFrame, 可视类由三个关键的 Swing 组件构成,即 JTextField、 JButton 和 JTable.
不过,我们只是完成了第一部分工作的一半,下一步就要编写业务逻辑。利 用这些业务逻辑,我们可以在可视类和数据源之间进行数据的读取或写入。在这 个案例中,我们的数据源就是 XML 文本。此时,可视化编辑器中的 GUI 如图 5 所示。
图 5:MyBooks GUI
Java 数据工厂的主要功能在于读取 XML 文件的内容。不过,在我们创建 Java 数据工厂以前,我们得先创建 XML 文件和两个数据类型:
创建 XML 文件
在 MyBooks 项目中新建一个文件,命名为 books.xml ,然后把下面的这些 内容复制到所生成的文件中:
Parkin, Burrus, Pullin
Sibley
创建 book 数据类型
XML 文件的每个条目都会存储在 book 对象中。新建一个 JAVA 类,并把它 命名为ve.book,然后把下面的代码粘贴到文件内容中: =package ve;
import com.ibm.etools.xmlschema.beans.*;
public class book extends ComplexType {
public book() {
}
public void setTitle(String title) {
setElementValue("title", title);
}
public String getTitle() {
return getElementValue("title");
}
public boolean removeTitle() {
return removeElement("title");
}
public void setAuthor(String author) {
setElementValue("author", author);
}
public String getAuthor() {
return getElementValue("author");
}
public boolean removeAuthor() {
return removeElement("author");
}
public void setCopyrightDate(String copyrightDate) {
setElementValue("copyrightDate", copyrightDate);
}
public String getCopyrightDate() {
return getElementValue ("copyrightDate");
}
public boolean removeCopyrightDate () {
return removeElement("copyrightDate");
}
}
创建 books 的数据类型
books 对象存储 book 的条目清单,
电脑资料
《利用Rational Application Developer Visual Editor实现Sw》(http://meiwen.anslib.com)。新建一个 JAVA 类,并把它命名为 ve.books ,将内容设置为:package ve;
import com.ibm.etools.xmlschema.beans.*;
public class books extends ComplexType {
public books() {
}
public void setBook(int index, book book) {
setElementValue(index, "book", book);
}
public book getBook(int index) {
return (book) getElementValue("book", "book", index);
}
public int getbookCount() {
return sizeOfElement ("book");
}
public boolean removeBook(int index) {
return removeElement(index, "book");
}
}
创建 Java 数据工厂
新建一个 Java 类,并把它命名为 ve.MyBooksDataSource,其内容如下: package ve;
import com.ibm.etools.xmlschema.beans.*;
public class MyBooksDataSource extends Factory {
public MyBooksDataSource() {
super();
}
public book[] getBooks() {
books iBooks = (books) loadDocument("books", getXMLFilename());
book[] result = new book[iBooks.getbookCount()];
for (int i = 0; i < iBooks.getbookCount(); i++) {
result[i] = iBooks.getBook(i);
}
return result;
}
public BaseType loadDocument(String className, String filename) {
return super.loadDocument(className, filename);
}
}
如果我们现在运行 MyBooks 应用程序,会发现应用程序还没有数据内容,因 为所有的 Swing 组件都尚未和数据绑定。在接下来的这一部分,我们将把数据 绑定到可视化组件。
B 部分:使用可视化编辑器绑定 MyBooks 用户界面
我们继续以自顶向下的方式来构建 GUI,各个组件已经被放置好。一旦看上 去没什么缺陷,我们现在可以提供逻辑,使组件可以访问并更新数据。现在,我 们将可视化组件与对应的数据绑定起来。
打开 JFrame
在 Application Developer 中,选择 File => Import。
选择 Existing Project into Workspace,然后按下 Next 按钮。
选择之前已创建的 MyBooks 项目,然后按下 Finish 按钮。
在可视化编辑器中打开 ve.rad.MyBooksApp。
绑定文本域
选择 textfield,这时,在 textfield 的左上方会出现一个 Bind... 选项 。
选择 Bind...,会打开一个对话框,该对话框可以让您指定如何绑定到数据 的细节。
在 Field Data Bindings 窗口中,选择 New Data Source Data Object... 。
在 New Data Source Data Object 窗口中,选择 Java Bean Factory 作为 source type。
选择 Data source 下拉框后面的 New...。
在 Choose a Bean 窗口中,搜索并选择 ve.MyBooksDataSource。然后按下 OK 按钮以添加该数据源。
在 Source service 文本框中,选择 getXMLFilename() ,这是数据源虚包 MyBooksDataSource.java 中一个方法的名称。
在 Name 文本域中,将 stringObject 改为 xmlFilename,然后按下 OK 按 钮。
再次按下 OK 按钮。
绑定表格
选择表格,在表格的左上方会出现一个 Bind... 选项
选择 Bind...。
在 Table Data Bindings 窗口中,选择 New Data Source Data Object... 。
在 New Data Source Data Object 窗口中,只出现一个 source service 方 法 getBooks(),这是返回数组数据的唯一方法,这些数据可以在表格中使用。 按下 OK 按钮,这时我们就选用了 getBooks() 方法。
将数据对象属性 author、copyrightDate及 title 添加到表格的列清单中。
按下 OK 按钮。
在可视化编辑器中,选择非可视 bean MyBooksDataSource,打开或激活 Properties 视图。
展开属性 dataSource。
将属性 encoding 设为 UTF-8 ,然后按下 Enter 按钮。
将属性 encodingTab 设为 UTF-8 ,然后按下 Enter按钮。
将属性 packageName 设为 ve,然后按下 Enter 按钮。
将属性 xmlFilename 设为 filename ,并按下 Enter. 按钮,然后在代码编 辑器中修改生成的代码, 将
myBooksDataSource1.setXMLFilename("filename");
改为:
myBooksDataSource3.setXMLFilename(filename);.
绑定按钮
选择按钮,在按钮的左上方会出现一个Bind...选项
选择 Bind... .
在 Component Action Bindings 窗口中,选择 source service 文本框里的 save(java.lang.String)。
在 Argument 下拉列表框中,选择 xmlFilename
按下 OK 按钮。
保存文件。
现在,MyBooks 应用程序已完成,图 6 显示的是该程序的屏幕截图。
图 6:已完成的 MyBooks 应用程序
测试应用程序
为了测试您的应用程序,您需要在运行配置中提供 XML 文件名作为参数:
在工具条上,选择 Run 图标旁的箭头,并选择 Run...
在 Run 窗口中,选择 Java Application 作 为启动程序。
按下 New,在窗口中会弹出一个新的运行配置框,Main 选项卡中,填入您的项目名 MyBooks 和应用程序名 ve.rad.MyBooksApp。
选择 Arguments 选项卡,输入 XML 文件名的全路径,当应用程序启动时,在 Arguments 选项卡中填写的程序参数将被传递给 main(String[] args) 方法,这就是该应用程序获得参数值的方法。
选择 Run。
更改 XML 文件名。
按下 Save 按钮。检查表格的内容是否被保存到指定的文件和位置。
关闭 MyBooksApp。
C 部分: 使用 Eclipse 可视化编辑器绑定 MyBooks 用户界面(可选)
本部分是可选择,因为它描述的是使用 Eclipse 可视化编辑器(它没有数据绑定工具)来绑定第一部分中创建的用户界面,本部分的目的是与 Application Developer 提供的绑定工具进 行对比,从而凸显使用数据绑定工具的优势。
为了使用 Eclipse 可视化编辑器,我们需要以下组件(这些组件可以从 Eclipse 可视化编辑器项目中下载):
Eclipse build eclipse-SDK 3.0.1
Visual Editor 1.0.2
EMF build 2.0.1
GEF build 3.0.1
创建表格模型
为了在运行时显示表格,你必须为表格模型提供实际数据,然后将表格模型和 JTable bean 相关联。表格模 型提供了多种可以被 JTable bean 调用的方法,利用这些方法,JTable bean 就能获取一些信息,如表格的行数和列数,或者是用在特定表格单元的数据。您需要在表格模型类中实现这些方 法,这样,JTable bean 就可以访问模型中的数据,并在表格视图中显示出来。
下面,我们新建一个 JAVA 类,并命名为 ve.eclipse.MyBooksTableModel。用下面的代码代替所生成的文件的内容:
package ve.eclipse;
import javax.swing.table.AbstractTableModel;
import ve.*;
public class MyBooksTableModel extends AbstractTableModel {
private MyBooksDataSource iBooksFactory;
private books iBooks;
public MyBooksTableModel() {
super();
}
public MyBooksTableModel(String xmlFile) {
super();
iBooksFactory = new MyBooksDataSource();
iBooksFactory.setPackageName("ve");
iBooksFactory.setEncoding("UTF8");
iBooksFactory.setEncodingTag("UTF-8");
iBooks = (books) iBooksFactory.loadDocument("books", xmlFile);
}
public String getXMLFile() {
return iBooksFactory.getXMLFilename();
}
public void setXMLFile(String filename) {
iBooksFactory.setXMLFilename(filename);
}
public void save(String fname) {
iBooksFactory.save(fname);
}
public int getColumnCount() {
return 3;
}
public int getRowCount() {
return iBooks.getbookCount();
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0: return iBooks.getBook(rowIndex).getTitle();
case 1: return iBooks.getBook(rowIndex).getAuthor();
case 2: return iBooks.getBook(rowIndex).getCopyrightDate();
}
return null;
}
public String getColumnName(int arg0) {
switch (arg0) {
case 0: return "Title";
case 1: return "Author";
case 2: return "Copyright Date";
}
return "";
}
}
绑定表格 table
a.在可视化编辑器中打开 ve.eclipse.MyBooksApp.java。
b.从选项板中选择 Choose Bean ,会弹出 Choose a Bean 对话框。
c.找到 ve.eclipse.MyBooksTableModel,并按下 OK 按钮。
d.把非可视 bean 放到可视化编辑器中,注意不要和 JFrame. 重叠,这一操作将生成 getMyBooksTableModel()。
e.修改 getMyBooksTableModel(),使其如下所示:
private MyBooksTableModel getMyBooksTableModel() {
if (myBooksTableModel == null) {
myBooksTableModel = new MyBooksTableModel(filename);
}
return myBooksTableModel;
}
f.在 Java Beans 视图中,选择 table。
g.修改 getJTable(),使其如下所示:
private JTable getJTable() {
if (jTable == null) {
jTable = new JTable();
jTable.setModel(getMyBooksTableModel());
}
return jTable;
}
绑定文本域
a.在 Java Beans 视图中选择 text field。
b.修改 getJTextField(),使其如下所示:
private JTextField getJTextField() {
if (jTextField == null) {
jTextField = new JTextField();
jTextField.setText(filename);
}
return jTextField;
}
绑定按钮 button
a.右键单击 SAVE 按钮,并选择 Events => actionPerformed.
b.修改 getJButton(),如下所示:
private JButton getJButton() {
if (jButton == null) {
jButton = new JButton();
jButton.setText("SAVE");
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
getMyBooksTableModel().save(getJTextField().getText());
}
});
}
return jButton;
}
c.保存文件。
5.测试应用程序
为了测试您的应用程序,您需要在运行配置中提供 XML 文件名作为参数:
a.在工具条上,选择 Run 图标旁的箭头,然后选择 Run...
b.在 Run 窗口中,选择 Java Application 作为启动程序。
c.按下 New 按钮,在窗口中会弹出一个运行配置框,然后在 Main 选项卡中,填写项目名 MyBooks,及应用程序名 ve.eclipse.MyBooksApp。
d.选择 Arguments 选项卡,输入 XML 文件名的全路径,当应用程序启动时,在 Arguments 选项卡中输入的程序参数将被传递给 main(String[] args) 方法, 这就是该应用程序获得参数值的方法。
e.选择 Run。
f.更改 XML 文件名。
g.按下 Save 按钮。检查表格内容是否被保存到指定的文件和位置。
h.关闭 MyBooksApp。
这个练习 的可选部分也完成了。你会注意到,许多步骤都需要手工编写代码将数据绑定到用户界面,尤其是表格模型。相比之下,Application Developer 的可视化编辑器提供了非常简便的用户界面 ,利用它,绝大部分代码都可以自动生成。
结束语
Application Developer Visual Editor 为我们提供了很多易于使用的工具。利用它,只需对生成的代码作小小的改动,即可绑定 Swing 可视化组件,如文本域、表格、按钮。使用文档模型可以自动设置文本域中的文本;且表格模型也是自动生成并被添加到表格组件中;操作被自动设置到按钮中。相比之下,用 Eclipse 完成同样的任务,则需要更多的手工处理。您必须创建自己的表格模型,并编写相关原代码,设置文本域中的文本,为按钮添加操作 ,并在表格上设置表格模型。现在, Application Developer 的价值已经很清晰了;您可以马上用它来简化 J2EE 应用程序的开发。