将列添加到退出TableModel

我有课;

public class A extends AbstractTableModel { ... } 

使用ResultSetMetaData我构建TableModel以匹配数据库中的结果集。

 public class B extends JPanel { ... } 

B类中 ,我扩展了JPanel并添加了A类来显示我的表。 我希望能够根据条件向表模型添加新列。 我试过google搜索,但大多数示例都是基于DefaultTableModel而不是AbstractTableModel

有谁知道如何实现这一目标?

只需扩展DefaultTableModel,然后您就可以访问其所有方法。 DefaultTableModel还扩展了AbstractTableModel,因此在代码的其他部分中对AbstractTableModel的引用不会中断。

例如

 import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.table.*; public class TableColumnHider { private JTable table; private TableColumnModel tcm; private Map hiddenColumns; public TableColumnHider(JTable table) { this.table = table; tcm = table.getColumnModel(); hiddenColumns = new HashMap(); } public void hide(String columnName) { int index = tcm.getColumnIndex(columnName); TableColumn column = tcm.getColumn(index); hiddenColumns.put(columnName, column); hiddenColumns.put(":" + columnName, new Integer(index)); tcm.removeColumn(column); } public void show(String columnName) { Object o = hiddenColumns.remove(columnName); if (o == null) { return; } tcm.addColumn((TableColumn) o); o = hiddenColumns.remove(":" + columnName); if (o == null) { return; } int column = ((Integer) o).intValue(); int lastColumn = tcm.getColumnCount() - 1; if (column < lastColumn) { tcm.moveColumn(lastColumn, column); } } public static void main(String[] args) { String[] columnNames = {"Name", "Size", "Type", "Date Modified", "Permissions"}; String[][] data = { {"bin", "2", "dir", "Jun 9", "drwxr-xr-x"}, {"boot", "3", "dir", "Jun 9", "drwxr-xr-x"}, {"dev", "6", "dir", "Jul 12", "drwxr-xr-x"}, {"etc", "34", "dir", "Jul 12", "drwxr-xr-x"},}; JTable table = new JTable(data, columnNames); table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane scrollPane = new JScrollPane(table); final TableColumnHider hider = new TableColumnHider(table); JPanel checkBoxes = new JPanel(); for (int i = 0; i < columnNames.length; i++) { JCheckBox checkBox = new JCheckBox(columnNames[i]); checkBox.setSelected(true); checkBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { JCheckBox cb = (JCheckBox) evt.getSource(); String columnName = cb.getText(); if (cb.isSelected()) { hider.show(columnName); } else { hider.hide(columnName); } } }); checkBoxes.add(checkBox); } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(scrollPane); frame.getContentPane().add(checkBoxes, BorderLayout.SOUTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } } 

只是为了好玩,这里是@ mKorbel的TableColumnHider的通用版本。

 import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.table.*; /** @see https://stackoverflow.com/questions/6796673 */ public class TableColumnHider { private JTable table; private TableColumnModel tcm; private Map hidden = new HashMap(); public TableColumnHider(JTable table) { this.table = table; this.tcm = table.getColumnModel(); } public void hide(String columnName) { int index = tcm.getColumnIndex(columnName); TableColumn column = tcm.getColumn(index); IndexedColumn ic = new IndexedColumn(index, column); if (hidden.put(columnName, ic) != null) { throw new IllegalArgumentException("Duplicate column name."); } tcm.removeColumn(column); } public void show(String columnName) { IndexedColumn ic = hidden.remove(columnName); if (ic != null) { tcm.addColumn(ic.column); int lastColumn = tcm.getColumnCount() - 1; if (ic.index < lastColumn) { tcm.moveColumn(lastColumn, ic.index); } } } private static class IndexedColumn { private Integer index; private TableColumn column; public IndexedColumn(Integer index, TableColumn column) { this.index = index; this.column = column; } } public static void main(String[] args) { String[] columnNames = { "Name", "Size", "Type", "Date Modified", "Permissions" }; String[][] data = { {"bin", "2", "dir", "Jun 9", "drwxr-xr-x"}, {"boot", "3", "dir", "Jun 9", "drwxr-xr-x"}, {"dev", "6", "dir", "Jul 12", "drwxr-xr-x"}, {"etc", "34", "dir", "Jul 12", "drwxr-xr-x"} }; JTable table = new JTable(data, columnNames); table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane scrollPane = new JScrollPane(table); final TableColumnHider hider = new TableColumnHider(table); JPanel checkBoxes = new JPanel(); for (int i = 0; i < columnNames.length; i++) { JCheckBox checkBox = new JCheckBox(columnNames[i]); checkBox.setSelected(true); checkBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { JCheckBox cb = (JCheckBox) evt.getSource(); String columnName = cb.getText(); if (cb.isSelected()) { hider.show(columnName); } else { hider.hide(columnName); } } }); checkBoxes.add(checkBox); } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(scrollPane); frame.getContentPane().add(checkBoxes, BorderLayout.SOUTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } } 

当然DefaultTableModel更方便,但AbstractTableModel提供了更大的灵活性和更少的开销。 这里有一个示例,显示包含List的模型,其中Value是POJO 。 可以在此处找到更多示例。

请注意, mKorbel和trashgod中的代码示例不保留列的原始顺序。 只是尝试按顺序隐藏所有列,然后再次以相同的顺序显示它们(Name-> Size-> Type-> Date Modified-> Permissions),您将看到原始订单丢失。

如果您需要在再次显示列时保留列的原始顺序,请查看Stephen Kelvin的解决方案 。

不幸的是,“视图”和“模型”之间的混淆在JTable API中很普遍。 即使是方法名称也会产生误导。 对于一些启示,请参阅此处的相关讨论。

我已将DefaultTableModel的addColumn方法修改为自定义AbstractTableModel,如下所示。 假设列标识符(标题)和模型数据(localCache)都是ArrayLists – 模型数据是ArrayList的ArrayList。

 public void addColumn(String columnName, List columnData) { headers.add(columnName); colCount = headers.size(); if (columnData != null) { for (int r = 0; r < localCache.size(); r++) { ((List)localCache.get(r)).add(columnData.get(r)); } } else { System.out.println("Null columnData passed"); } fireTableStructureChanged(); }