使用JComboBox更改/更新JTable内容(类别)

我的JTable有问题。 我的JTable显示数据库的内容。 一个数据库表具有名称类别。 每个类别都显示在JComboBox中。 如果我点击某个类别,它应该更新表格内容。

这是我的代码短片,所以它更容易帮助我。 代码应该是可运行的:

(TestClass – Main)

package test; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.LinkedList; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; public class TestClass implements ActionListener{ String[] header = {"head", "head", "head"}; Object[][] data = {{Boolean.FALSE, "text", "text"}, {Boolean.FALSE, "text", "text"}, {Boolean.FALSE, "text", "text"}}; LinkedList newdata = new LinkedList(); String[] combolist = {"apple", "banana", "cranberry"}; JComboBox combobox = new JComboBox(combolist); JTable table = new JTable(new TestTableModel(data, header)); JFrame frame = new JFrame(); JPanel panel = new JPanel(new GridLayout(1, 0, 1, 0)); public TestClass() { combobox.addActionListener(this); panel.add(combobox); frame.add(panel, BorderLayout.NORTH); frame.add(new JScrollPane(table), BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); frame.setVisible(true); frame.pack(); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == this.combobox) { JComboBox combobox = this.combobox; newdata.add("Test1"); newdata.add("Test2"); TestTableModel model = (TestTableModel) table.getModel(); int i = 0; for (String text : newdata) { data[i][0] = Boolean.TRUE; data[i][1] = text; data[i][2] = text; i++; } model.setData(data); } } public static void main(String[] args) { new TestClass(); } } 

(TestTableModel – 如果需要AbstractTableModel(你需要它来执行代码!))

 package test; import javax.swing.table.AbstractTableModel; public class TestTableModel extends AbstractTableModel { private static final long serialVersionUID = 5044877015250409328L; private String[] header; private Object[][] data; public TestTableModel(Object[][] data, String[] header) { this.header = header; this.data = data; } public void setData(Object[][] data) { this.data = data; fireTableDataChanged(); } @Override public Class getColumnClass(int column) { if (column == 0) { return Boolean.class; } return super.getColumnClass(column); } @Override public int getColumnCount() { return header.length; } @Override public String getColumnName(int column) { return header[column]; } @Override public int getRowCount() { return data.length; } @Override public Object getValueAt(int row, int column) { return data[row][column]; } @Override public boolean isCellEditable(int row, int column) { return column == 0; } @Override public void setValueAt(Object value, int row, int column) { data[row][column] = value; } } 

使用此短代码,如果更改类别,表格将冻结。 在我的整个代码中,它也冻结了,但是当我调整窗口大小时,我能够在后台看到更新的表格(表格大小调整为与框架相同的大小)。 我不知道为什么它不是在破碎。

编辑:改变内容的问题已经解决。 来源已更新。 但是,获得正确的表格大小的问题已经解决了。 在源代码中,我首先使用3行数组,然后使用2行数组。 我想删除旧表并创建一个新表,因此行大小是正确的。

基本上我只想用新内容更新表。

  • 谢谢你的帮助!

代码是错误的,因为每次调用actionPerformed() ,您都在创建一个新组件:

 table = new JTable(new TestTableModel(data, header)); frame.add(new JScrollPane( table )); // <-- BTW: here you need to put the table otherwise you are adding an empty JScrollPane frame.validate(); 

(注意:还有一个bug,@ mKorbel提到了它)。

但是,您已经在框架中添加了一个带有JTableJScrollPane ,并且这些内容仍然存在。 (如果您尝试调整窗口大小,您将看到旧表格下方的新表格)。

更新表数据的正确方法是让其TableModel进行模型中所需的任何修改,然后根据您更改的内容,您将触发apporpriate fireXXX()方法以通知表重绘自身。

作为一个粗略的例子,您的代码将是:

 @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == this.combobox) { JComboBox combobox = this.combobox; newdata.clear(); // Clear your list or create a new one otherwise data will keep piling up. newdata.add("Test1"); newdata.add("Test2"); TestTableModel model = (TestTableModel) table.getModel(); // Since you need to replace the whole data create a new Object[][] each time Object[][] newModelData = new Object[newdata.size()][3]; // Set whatever data to the new array int i = 0; for (String text : newdata) { newModelData[i][0] = Boolean.TRUE; newModelData[i][1] = text; newModelData[i][2] = text; i++; } // replace all data of the current model model.setData(newModelData); } } .... // Now inside your table model: ... @Override public Class getColumnClass(int column) { // if (column == 0) { // return Boolean.class; // <-- this produces a ClassCastException with the data you aretrying to set // } return super.getColumnClass(column); } public void setData(Object[][] data) { this.data = data; // <-- Update the data fireTableDataChanged(); // <-- fire the event so the table is notified. If you change only one cell you need to call the appropriate fire event } ... 

更新1:您的新代码问题已修复了更新模型中数据的方式。 但是,更新data结构时存在逻辑缺陷。 此变量以3行数组开头。 在actionPerformed()方法中,为新数据列表的长度执行一个循环,该循环只有2个条目。 因此,您只更新模型的前两行。

更新2:似乎你错过了这一点。 如何更新模型在这里很重要。 该表将显示您的模型具有的任何数据。 如果您只更新了2行但未修改第3行,则表格将显示3行(2个新行和1个旧行)。 由于每次需要更改所有数据,因此您需要完全替换模型中的数据 。 每次不是表格时,都需要重新创建数据。 请参阅更新代码示例。 我添加了actionPerformed()方法,该方法使用当前源代码重新初始化数据。 请阅读内联评论。

更改jtable中的数据后,请尝试以下代码。

model.fireTableDataChanged(); table.repaint();

其中model是tablemodel对象,table是JTable对象

我希望它有所帮助!