我的jtable有问题。
我有许多线程,每个线程都必须向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) {
}
答案 0 :(得分:7)
Swing的第一条规则 - 不要从事件调度线程以外的任何线程修改UI
首先,使用SwingUtilities#invokeLater
确保您的更新调用已同步,或者更新对代码路径SwingUtilities#invokeAndWait
向表模型添加行时,您负责触发通知视图模型已更改所需的更新事件。
如果您使用的是DefaultTableModel
,那么这将为您完成,如果您使用的是AbstractTableModel
,或者您拥有TableModel
,那么您需要自己执行此操作。
最简单的方法是编写一个从AbstractTableModel
延伸并从add方法中调用AbstractTableModel#fireTableRowsInserted(int, int)
的实现,这将告诉JTable
模型已添加行并将导致表格会自动更新。
不要被愚弄,使用fireTableRowsInserted
通常比在向表模型添加行时使用fireTableDataChanged
更快,因为整个表不需要重新绘制。如果您已经显着更改了表格(添加/删除/更新了许多行),那么fireTableDataChanged
将比单个插入/删除/更新的系列调用更快。
有关详细信息,请查看How to Use Tables和Concurrency in Swing
<强>已更新强>
因为看起来我可能没有说清楚。该模型负责解雇事件。这意味着,在您的add方法中,您应该调用fireTableRowsInserted
。您应该避免从外部源调用这些方法。
答案 1 :(得分:1)
Swing不是线程安全的。如果需要从AWT事件派发线程以外的线程修改Swing组件,请使用
SwingUtilities.invokeLater(new Runnable(){public void run() {
// your code
}});
答案 2 :(得分:0)
您能否澄清一下如何添加行?希望使用模型,对吧? 添加新行后,您必须调用模型的方法fireTableDataChanged / 不是最佳选项 /或fireTableRowsInserted / 更好 / 并且不要忘记使用SwingUtilities.invokeLater来避免Swing的问题
答案 3 :(得分:0)
public class TM extends AbstractTableModel {
final List<Integer>ids;
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);
答案 4 :(得分:0)
此外,在尝试更新JTable
的模型时,在更新模型之前删除任何tableModelListener
非常重要。我用model.addColumn()
和table.moveColumn()
看到了这个观察结果。确保在对模型进行任何更改后添加tableModelListener
。
答案 5 :(得分:-1)
我希望你知道Swing不是线程安全的(除了少数例外)。你需要在你的代码中处理它。