在前面的介绍中,我们了解了数种在不同组件上的事件处理。同样,在JTable的事件大致均针对表格内容的异操作处理,包括字段内容改变,列数增加 或减少,行数增加或减少,或是表格的结构改变等等。这些事件我们称为TableModelEvent事件。要处理 TableModelEvent事件我们必须实现TableModelListener界面,此界面定义了一个方法,那就是tableChanged(),为了处理这些事件的种种 情况,在AbstractTableModel类中提供了下列方法来提示TableModelListener:表格内容已经改动了,如下所示:
在知道在表格中可能发生的事件后,我们要如何拦截这些事件的信息呢?在AbstractTableModel类中提供了一个注册listener的方法 :addTableModelListener().在加入TableModelListener之后,我们就可以依照不同的事件做不同的处理了。
先来看看下面的例子吧,这个例子主要是更改本章的ColumnModelTest.java范例,再加上一些功能。在这个范例中,我们针对用户对表格所做的修改加以处理,如果改的项目是数字,包括“语文”,“数学”字段,则我们直接将修改的值累加至"总分"字段,并检查其是 否及格且在“及格”字段作修改;而当我们勾起"作弊"列的Check Box选项时,若原本总分应为及格者,则设置为不及格,且总分改成119分。
import javax.swing.table.AbstractTableModel; import javax.swing.event.*; import javax.swing.table.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class TableEventHandle implements TableModelListener { JTable table = null; MyTable mt = null; JLabel label = null; // 显示修改字段位置 public TableEventHandle() { JFrame f = new JFrame(); mt = new MyTable(); mt.addTableModelListener(this); table = new JTable(mt); JComboBox c = new JComboBox(); c.addItem("Taipei"); c.addItem("ChiaYi"); c.addItem("HsinChu"); table.getColumnModel().getColumn(1).setCellEditor( new DefaultCellEditor(c)); table.setPreferredScrollableViewportSize(new Dimension(550, 30)); JScrollPane s = new JScrollPane(table); label = new JLabel("修改字段位置:"); f.getContentPane().add(s, BorderLayout.CENTER); f.getContentPane().add(label, BorderLayout.SOUTH); f.setTitle("TableEventHandle"); f.pack(); f.setVisible(true); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } public void tableChanged(TableModelEvent e) { int row = e.getFirstRow(); int column = e.getColumn(); label.setText("修改字段位置:" + (row + 1) + " 行 " + (column + 1) + " 列"); boolean cheat = ((Boolean) (mt.getValueAt(row, 6))).booleanValue(); int grade1 = ((Integer) (mt.getValueAt(row, 2))).intValue(); int grade2 = ((Integer) (mt.getValueAt(row, 3))).intValue(); int total = grade1 + grade2; if (cheat) { if (total > 120) mt.mySetValueAt(new Integer(119), row, 4); else mt.mySetValueAt(new Integer(total), row, 4); mt.mySetValueAt(new Boolean(false), row, 5); } else { if (total > 120) mt.mySetValueAt(new Boolean(true), row, 5); else mt.mySetValueAt(new Boolean(false), row, 5); mt.mySetValueAt(new Integer(total), row, 4); } table.repaint(); } public static void main(String args[]) { new TableEventHandle(); } } class MyTable extends AbstractTableModel { Object[][] p = { { "阿呆", "Taipei", new Integer(66), new Integer(32), new Integer(98), new Boolean(false), new Boolean(false) }, { "阿瓜", "ChiaYi", new Integer(85), new Integer(69), new Integer(154), new Boolean(true), new Boolean(false) } }; String[] n = { "姓名", "居住地", "语文", "数学", "总分", "及格", "作弊" }; public int getColumnCount() { return n.length; } public int getRowCount() { return p.length; } public String getColumnName(int col) { return n[col]; } public Object getValueAt(int row, int col) { return p[row][col]; } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } public void setValueAt(Object value, int row, int col) { p[row][col] = value; fireTableCellUpdated(row, col); } public void mySetValueAt(Object value, int row, int col) { p[row][col] = value; } }