线程和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不是线程安全的(少数例外)。 您需要在代码中处理这个问题。