线程和jtable
我有jtable的问题。
我有许multithreading,每个线程都必须向jTable添加一行,但表格仍为空。 我正在使用netbeans,图形完全独立于逻辑。 有人能帮助我吗?
这是我用来添加行的代码
MainGui.java
public void addToTable(String from, String to, int request, int response, String timeElapsed) { Object [][] temp = new Object [data.length + 1][5]; for (int i = 0; i < data.length; i++) { for (int j = 0; j < 5; j++) { temp[i][j] = data[i][j]; } } temp[data.length][0] = from; temp[data.length][1] = to; temp[data.length][2] = request; temp[data.length][3] = response; temp[data.length][4] = timeElapsed; data = temp; table.setModel(new DefaultTableModel(data, columnName)); }
MyThread.java
public void run() { try { MainGui mg = new MainGui(); mg.addtotable("null", "null", 0, 0, "null"); } catch (Exception e) { }
Swing的第一条规则 – 不要从事件调度线程以外的任何线程修改UI
首先,使用SwingUtilities#invokeLater
确保更新调用是同步的,或者更新是否对代码路径至关重要SwingUtilities#invokeAndWait
向表模型添加行时,您负责触发通知视图模型已更改所需的更新事件。
如果您正在使用DefaultTableModel
那么这将为您完成,如果您正在使用AbstractTableModel
或您拥有TableModel
那么您将需要自己执行此操作。
最简单的方法是编写一个从AbstractTableModel
扩展的实现,并从add方法中调用AbstractTableModel#fireTableRowsInserted(int, int)
,这将告诉JTable
模型已添加行并将使表自动更新。
不要被愚弄,使用fireTableRowsInserted
通常比在向表模型添加行时使用fireTableDataChanged
更快,因为整个表不需要重新绘制。 如果您已经显着更改了表(添加/删除/更新了许多行),那么fireTableDataChanged
将比单个插入/删除/更新的系列调用更快。
有关更多信息,请查看如何 在Swing中 使用表和并发
更新
因为看起来我可能没有说清楚。 该模型负责解雇事件。 这意味着,在你的add方法中,你应该调用fireTableRowsInserted
。 您应该避免从外部源调用这些方法。
Swing不是线程安全的。 如果需要从AWT事件派发线程以外的线程修改Swing组件,请使用
SwingUtilities.invokeLater(new Runnable(){public void run() { // your code }});
您能否澄清一下如何添加行? 希望使用模型,对吧? 一旦添加了新行,你必须调用模型的方法fireTableDataChanged / 不是最佳选项 /或fireTableRowsInserted / better /并且不要忘记使用SwingUtilities.invokeLater来避免问题Swing
public class TM extends AbstractTableModel { final Listids; public TM() { ids = new ArrayList(); } @Override public int getRowCount() { return ids.size(); } @Override public int getColumnCount() { return 1; } @Override public String getColumnName(int column) { if(column == 0) { return "ID"; } else { return "UNDEF"; } } @Override public Object getValueAt(int rowIndex, int columnIndex) { if(columnIndex == 0) { return ids.get(rowIndex); } else { return "NaN"; } } public void addId(final int id) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { insertNewRow(id); } }); } private void insertNewRow(int id) { ids.add(id); int rowIndex = ids.size(); fireTableRowsInserted(rowIndex, rowIndex); } } //Somewhere in your code TM myModel = new TM(); myTable = new JTable(myModel); //Somewhere from thread: myModel.addId(123); //Somewhere from another thread: myModel.addInd(455);
此外,在尝试更新JTable
模型时,在更新模型之前删除任何tableModelListener
非常重要。 我用model.addColumn()
和table.moveColumn()
看到了这个观察结果。 确保在对tableModelListener
进行任何更改后添加tableModelListener
。
我希望你知道Swing不是线程安全的(少数例外)。 您需要在代码中处理这个问题。