49 /**
50 * The BeanTableModel automatically returns false, and if you
51 * need to make an editable table, you'll have to subclass
52 * BeanTableModel and override this function.
53 */
54 public boolean isCellEditable(int row, int col)
55 {
56 return false;
57 }
58 /**
59 * The function that returns the value that you see in the JTable. It gets
60 * the BeanMap wrapping the JavaBean based on the row, it uses the
61 * column number to get the field from the column information LinkedMap,
62 * and then uses the field to retrieve the value out of the BeanMap.
63 */
64 public Object getValueAt(int row, int col)
65 {
66 BeanMap map = (BeanMap)mapValues.get(row);
67 return map.get(columnInfo.getValue(col));
68 }
69 /**
70 * The opposite function of the getValueAt -- it duplicates the work of the
71 * getValueAt, but instead puts the Object value into the BeanMap instead
72 * of retrieving its value.
73 */
74 public void setValueAt(Object value, int row, int col)
75 {
76 BeanMap map = (BeanMap)mapValues.get(row);
77 map.put(columnInfo.getValue(col), value);
78 super.fireTableRowsUpdated(row, row);
79 }
80
81 /**
82 * The BeanTableModel implements the CollectionListener interface
83 * (1 of the 3 parts of the framework) and thus listens for changes in the
84 * data it is modeling and automatically updates the JTable and the
85 * model when a change occurs to the data.
86 */
87 public void collectionChanged(CollectionEvent e)
88 {
89 initializeValues((Collection)e.getSource());
90 super.fireTableDataChanged();
91 }
正如您所看到的,BeanTableModel 的整个 TableModel 足够通用化,可以在任何表中使用。它充分利用了内省机制,省去了所有特定于 bean 的编码工作,在传统的 TableModel 中,这类编码工作绝对是必需的 —— 同时也是完全冗余的。BeanTableModel 还可以在 TMF 框架之外使用,虽然在外面使用会丧失一些威力和灵活性。
看过这段代码之后,您会提出两个问题。首先,BeanTableModel 从哪里获得列名-字段与键-值配对的信息?第二,到底什么是 ObservableCollection ?这些问题会将我们引入框架的接下来的两个部分。这些问题的答案以及更多的内容,将在本文后面接下来的章节中出现。
Castor XML 解析器
保存必需的列名-字段信息的最合理的位置位于 Java 类之外,这样,不需要再重新编译 Java 代码,就可以修改这个信息。因为关于列名和字段的信息是 TMF 框架中惟一明确与表有关的信息,这意味着整个表格都可以在外部进行配置。
显然,该解决方案会自然而然把 XML 作为配置文件的语言选择。配置文件必须为多种表模型保存信息;您还需要能够用这个文件指定每个列中的数据。配置文件还应当尽可能地易于阅读,因为开发人员之外的人员有可能要修改它。
这些问题的最佳解决方案是 Castor XML 解析器。查看 Castor 实际使用的最佳方法就是查看如何在框架中使用它。
让我们来考虑一下配置文件的目的:保存表模型和表中列的信息。 XML 文件应当尽可能简单地显示这些信息。TMF 框架中的 XML 文件用清单 3 所示的格式来保存表模型信息。
清单3. TMF 配置文件示例
1 <model>
2 <className>demo.hr.TableModelFreeExample</className>
3 <name>Hire</name>
4 <column>
5 <name>First Name</name>
6 <field>firstName</field>
7 </column>
8 <column>
9 <name>Last Name</name>
10 <field>lastName</field>
11 </column>
12 </model>
13
与这个目的相反的目标是,开发人员必须处理的 Java 对象应当像 XML 文件一样容易理解。通过 Castor XML 解析器用来存储 href="http://storage.it168.com/" target=_blank>存储列信息的三个 Java 对象,就可以看到这一点,这三个对象是: TableData (存储文件中的所有表模型)、 TableModelData (存储特定于表模型的信息)和 TableModelColumnData (存储列信息)。这三个类提供了 Java 开发人员所需的所有包装器,以便得到有关 TableModel 的所有必要信息。
将所有这些包装在一起所缺少的一个环节就是 映射文件,它是一个 XML 文件,Castor 用它把简单的 XML 映射到简单的 Java 对象中。在完美的世界中,映射文件也应当很简单,但事实要比这复杂得多。良好的映射文件要使别的一切东西都保持简单;所以一般来说,映射文件越复杂,配置文件和 Java 对象就越容易处理。映射文件所做的工作顾名思义就是把 XML 对象映射到 Java 对象。清单 4 显示了 TMF 框架使用的映射文件。
清单 4. TMF 框架使用的 Castor 映射文件
1 <?xml version="1.0"?>
2 <mapping>
3 <description>A mapping file for externalized table models</description>
4
5 <class name="com.ibm.j2x.swing.table.TableData">
6 <map-to xml="data"/>
7 <field name="tableModelData" collection="arraylist" type=
8 "com.ibm.j2x.swing.table.TableModelData">
9 <bind-xml name="tableModelData"/>
10 </field>
11 </class>
12
13 <class name="com.ibm.j2x.swing.table.TableModelData">
14 <map-to xml="model"/>
15 <field name="className" type="string">
16 <bind-xml name="className"/>
17 </field>
18 <field name="name" type="string">
19 <bind-xml name="name"/>
20 </field>
21 <field name="columns" collection="arraylist" type=
22 "com.ibm.j2x.swing.table.TableModelColumnData">
23 <bind-xml name="columns"/>
24 </field>
25 </class>
26
27 <class name="com.ibm.j2x.swing.table.TableModelColumnData">
28 <map-to xml="column"/>
29 <field name="name" type="string">
30 <bind-xml name="name"/>
31 </field>
32 <field name="field" type="string">
33 <bind-xml name="field"/>
34 </field>
35 </class>
36
37 </mapping>
38
责任编辑:小草