12.11.3 TableColumnMode和监听器
JTable
使用TableModel
来保存该表格所有数据列的状态数据,如果程序需要访问JTable
的所有列状态信息,则可以通过获取该JTable
的TableColumnModel
来实现。TableColumnModel
提供了如下几个方法来增加、删除和移动数据列:
方法 |
描述 |
void addColumn(TableColumn aColumn) |
该方法用于为TableModel 添加一列。该方法主要用于将原来隐藏的数据列显示出来 |
void moveColumn(int columnIndex, int newIndex) |
该方法用于将指定列移动到其他位置。 |
void removeColumn(TableColumn column) |
该方法用于从TableModel 中删除指定列。实际上,该方法并未真正删除指定列,只是将该列在TableColumnModel 中隐藏起来,使之不可见。 |
注意:当调用removeColumn
删除指定列之后,调用TableColumnModel
的getColumnCount()
方法也会看到返回的列数减少了,看起来很像真正删除了该列。但使用setValueAt()
方法为该列设置值时,依然可以设置成功,这表明调用removeColumn
删除指定列之后,这些列依然是存在的
实际上,JTable
也提供了对应的方法来增加、删除和移动数据列,不过JTable
的这些方法实际上还是需要委托给它所对应的TableColumnModel
来完成。
图12.51显示了JTable
及其主要辅助类之间的关系:
图12.51 JTable及其主要辅助类之间的关系
程序
下面程序示范了如何通过DefaultTableModel
和TableColumnModel
动态地改变表格的行、列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| import java.util.ArrayList; import java.awt.BorderLayout; import javax.swing.*; import javax.swing.table.*;
public class DefaultTableModelTest { JFrame mainWin = new JFrame("管理数据行、数据列"); final int COLUMN_COUNT = 5; DefaultTableModel model; JTable table; ArrayList<TableColumn> hiddenColumns = new ArrayList<>();
public void init() { model = new DefaultTableModel(COLUMN_COUNT, COLUMN_COUNT); for (int i = 0; i < COLUMN_COUNT; i++) { for (int j = 0; j < COLUMN_COUNT; j++) { model.setValueAt("老单元格值 " + i + " " + j, i, j); } } table = new JTable(model); mainWin.add(new JScrollPane(table), BorderLayout.CENTER); JMenuBar menuBar = new JMenuBar(); mainWin.setJMenuBar(menuBar); JMenu tableMenu = new JMenu("管理"); menuBar.add(tableMenu); JMenuItem hideColumnsItem = new JMenuItem("隐藏选中列"); hideColumnsItem.addActionListener(event -> { int[] selected = table.getSelectedColumns(); TableColumnModel columnModel = table.getColumnModel(); for (int i = selected.length - 1; i >= 0; i--) { TableColumn column = columnModel.getColumn(selected[i]); table.removeColumn(column); hiddenColumns.add(column); } }); tableMenu.add(hideColumnsItem); JMenuItem showColumnsItem = new JMenuItem("显示隐藏列"); showColumnsItem.addActionListener(event -> { for (TableColumn tc : hiddenColumns) { table.addColumn(tc); } hiddenColumns.clear(); }); tableMenu.add(showColumnsItem); JMenuItem addColumnItem = new JMenuItem("插入选中列"); addColumnItem.addActionListener(event -> { int[] selected = table.getSelectedColumns(); TableColumnModel columnModel = table.getColumnModel(); for (int i = selected.length - 1; i >= 0; i--) { TableColumn column = columnModel.getColumn(selected[i]); table.addColumn(column); } }); tableMenu.add(addColumnItem); JMenuItem addRowItem = new JMenuItem("增加行"); addRowItem.addActionListener(event -> { String[] newCells = new String[COLUMN_COUNT]; for (int i = 0; i < newCells.length; i++) { newCells[i] = "新单元格值 " + model.getRowCount() + " " + i; } model.addRow(newCells); }); tableMenu.add(addRowItem); JMenuItem removeRowsItem = new JMenuItem("删除选中行"); removeRowsItem.addActionListener(event -> { int[] selected = table.getSelectedRows(); for (int i = selected.length - 1; i >= 0; i--) { model.removeRow(selected[i]); } }); tableMenu.add(removeRowsItem); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); }
public static void main(String[] args) { new DefaultTableModelTest().init(); } }
|
上面程序中的粗体字代码部分就是程序控制隐藏列、显示隐藏列、增加数据行和删除数据行的代码。除此之外,程序还实现了一个功能:当用户选中某个数据列之后,还可以将该数据列添加到该表格的后面——但不要忘记了add()
方法的功能,add
方法只是将已有的数据列显示出来,并不是真正添加数据列。运行上面程序,会看到如图12.52所示的界面。
从图12.52中可以看出,虽然程序新增了一列,但新增列的列名依然是B,如果修改新增列内的单元格的值时,看到原来的B列的值也随之改变。
如图12.52.2所示:
由此可见,addColumn方法只是将原有的列显示出来而已。程序还允许新增数据行,当执行addRows()
方法时需要传入数组或Vector
参数,该参数里包含的多个数值将作为新增行的数据。
监听JTable里列状态的改变
如果程序需要监听JTable
里列状态的改变,例如监听列的增加、删除、移动等改变,则必须使用该JTable
所对应的TableColumnModel
对象。
TableColumnModel
对象提供了一个addColumnModelListener()
方法来添加监听器
TableColumnModelListener
监听器接口里包含如下几个方法:
TableColumnModelListener方法 |
描述 |
void columnAdded(TableColumnModelEvent e) |
当向TableColumnModel 里添加数据列时将会触发该方法 |
void columnMarginChanged(ChangeEvent e) |
当由于页面距(Margin )的改变引起列状态改变时将会触发该方法 |
void columnMoved(TableColumnModelEvent e) |
当移动TableColumnMode 里的数据列时将会触发该方法 |
void columnRemoved(TableColumnModelEvent e) |
当删除TableColumnModel 里的数据列时将会触发该方法。 |
void columnSelectionChanged(ListSelectionEvent e) |
当改变表格的选择模式时将会触发该方法。 |
但表格的数据列通常需要程序来控制增加、删除,用户操作通常无法直接为表格增加、删除数据列,所以使用监听器来监听TableColumnModel
改变的情况比较少见。