12.11.2 TableModel和监听器
12.11.2 TableModel和监听器
与JList
、JTree
类似的是,JTable
采用了TableModel
来保存表格中的所有状态数据;与ListModel
类似的是,TableModel
也不强制保存该表格显示的数据。虽然在前面程序中看到的是直接利用一个二维数组来创建JTable
对象,但也可以通过TableModel
对象来创建表格。
使用TableModel创建表格
如果需要利用TableModel
来创建表格对象,则可以利用Swing
提供的AbstractTableModel
抽象类,该抽象类已经实现了TableModel
接口里的大部分方法,程序只需要为该抽象类实现如下三个抽象方法即可。
getColumnCount()
:返回该TableModel
对象的列数量。getRowCount()
:返回该TableModel
对象的行数量。getValueAt()
:返回指定行、指定列的单元格值。
重写这三个方法后只是告诉JTable
生成该表格所需的基本信息,如果想指定JTable
生成表格的列名,还需要重写getColumnName(int c)
方法,该方法返回一个字符串,该字符串将作为第c+1
列的列名。
设置单元格内容可修改
在默认情况下,AbstractTableModel
的isCellEditable
方法返回false
,表明该表格的单元格处于不可编辑状态,如果想让用户直接修改单元格的内容,则需要重写该方法,并让该方法返回true
。重写该方法后,只实现了界面上单元格的可编辑,如果需要控制实际的编辑操作,还需要重写该类的setValueAt
方法。
方法 | 描述 |
---|---|
boolean isCellEditable(int rowIndex, int columnIndex) |
Returns false. |
void setValueAt(Object aValue, int rowIndex, int columnIndex) |
This empty implementation is provided so users don’t have to implement this method if their data model is not editable. |
TableModel典型应用 封装JDBCResultset
关于TableModel
的典型应用就是用于封装JDBC
编程里的Resultset
,程序可以利用TableModel
来封装数据库査询得到的结果集,然后使用JTable
把该结果集显示岀来。还可以允许用户直接编辑表格的单元格,当用户编辑完成后,程序将用户所做的修改写入数据库。
程序
下面程序简单实现了这种功能——当用户选择了指定的数据表后,程序将显示该数据表中的全部数据,用户可以直接在该表格内修改数据表的记录
mysql.sql
1 | drop database if exists auction; |
conn.ini
1 | jdbc.drivers=com.mysql.jdbc.Driver |
TableModelTest.java
1 | import java.sql.*; |
上面程序的关键在于①号粗体字代码所扩展的ResultsetTableModel
类,该类继承了AbstractTableModel
父类,根据其Resultset
来重写getColumnCount
、getRowCount
和getValueAt
三个方法,从而允许该表格可以将该Resultset
里的所有记录显示出来。除此之外,该扩展类还重写了isCellEditabled
方式用来实现允许用户编辑单元格的功能,重写了setValueAt
两个方法用来实现当用户编辑单元格时将所做的修改同步到数据库的功能。
程序中的粗体字代码使用Resultset
创建了一个TableModel
对象,并为该TableModel
添加事件监听器,然后把该TableModel
使用JTable
显示出来。当用户修改该JTable
对应表格里单元格的内容时,该监听器会检测到这种修改,并将这种修改信息通过下面的文本域显示出来。
提示:上面程序大量使用了JDBC编程中的JDBC连接数据库、获取可更新的结果集、ResultSetMetaData、DatabaseMetaData等知识,读者可能一时难以读懂,可以参考本书第13章的内容来阅读本程序。该程序的运行需要底层数据库的支持,所以读者应按第13章的内容正常安装MySQI数据库,并将 codes\12\12.11路径下的mysql.sql脚本导入数据库,修改conn.ini文件中的数据库连接信息才可运行该程序。使用JDBC连接数据库还需要加载JDBC驱动,所以本章为运行该程序提供了一个run.cmd批处理文件,读者可以通过该文件来运行该程序。不要直接运行该程序,否则可能出现 java.lang.ClassNotFoundException:com.mysql.jdbc.Driver 。
运行上面程序,会看到如图12.50所示的界面。
从图12.50中可以看出,当修改指定单元格的记录时,添加在TableModel
上的监听器就会被触发。当修改JTable
单元格里的内容时,底层数据表里的记录也会做出相应的改变,如图12.50.1所示:
DefaultTableModel
不仅用户可以扩展AbstractTableModel
抽象类,Swing
本身也为AbstractTableModel
提供了一个DefaultTableModel
实现类,程序可以通过使用DefaultTableModel
实现类来创建Table
对象。通过DefaultTableModel
对象创建JTable
对象后,就可以调用它提供的方法来添加数据行、插入数据行、删除数据行和移动数据行。
DefaultTableModel
提供了如下几个方法来控制数据行操作。
DefaultTableModel 控制数据行的方法 |
描述 |
---|---|
addColumn() |
该方法用于为TableModel 增加一列,该方法有三个重载的版本,实际上该方法只是将原来隐藏的数据列显示出来。 |
addRow() |
该方法用于为TableModel 增加一行,该方法有两个重载的版本 |
insertRow() |
该方法用于在TableModel 的指定位置插入一行,该方法有两个重载的版本。 |
removeRow(int start, int end,int to) |
该方法用于移动TableModel 中指定范围的数据行 |
通过DefaultTableModel
提供的这样几个方法,程序就可以动态地改变表格里的数据行
Swing
为TableModel
提供了两个实现类,其中一个是DefaultTableModel
,另一个是JTable
的匿名内部类。
- 如果直接使用二维数组来创建
JTable
对象,维护该JTable
状态信息的model
对象就是JTable
匿名内部类的实例; - 当使用
Vector
来创建JTable
对象时,维护该JTable
状态信息的modl
对象就是DefaultTableModel
实例
提示:Swing为 TableModel 提供了两个实现类,其中一个是 DefaultTableModel,另一个是JTable的匿名内部类。如果直接使用二维数组来创建JTable对象,维护该 JTable状态信息的 model对象就是 JTable 匿名内部类的实例;当使用 Vector 来创建 JTable对象时,维护该 JTable 状态信息的 model对象就是 DefaultTableModel实例。