问题
I have a problem with jtable.
I have a number of threads and each of them have to add a row to the jTable, but the table remains empty. I'm working with netbeans, the graphics are totally separate from the logic. Can someone help me, please?
this is the code that i use for adding a row
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) {
}
回答1:
The first rule of Swing - Don't modify the UI from any Thread other then the Event Dispatching Thread
First, make sure your updates calls are synchronized, using SwingUtilities#invokeLater
or if the update is critical to the code path SwingUtilities#invokeAndWait
When adding rows to the table model, you are responsible for firing the update events required to notify the view that the model has changed.
If you're using a DefaultTableModel
then this will be done for you, if you're using an AbstractTableModel
or you own TableModel
then you will need to do this yourself.
The easiest way is to write an implementation that extends from AbstractTableModel
and call AbstractTableModel#fireTableRowsInserted(int, int) from within your add method, this will tell the JTable
that the model has added rows and will cause the table to update itself accordiningly.
Don't be fooled, using fireTableRowsInserted
is generally faster then using fireTableDataChanged
when adding rows to a table model as the whole table doesn't need to be repainted. If you've significantly changed the table (added/removed/updated lots of rows), then fireTableDataChanged
would be quicker than a series individual insert/deleted/updated calls.
Have a look at How to Use Tables and Concurrency in Swing for more information
UPDATED
As it appears as I may not have made myself clear. The model is responsible for fire the events. That means, that within your add method, you should be calling fireTableRowsInserted
. You should refrain from calling these methods from an external source.
回答2:
Swing is not thread-safe. If you need to modify Swing components from Threads other than the AWT event dispatch thread, use
SwingUtilities.invokeLater(new Runnable(){public void run() {
// your code
}});
回答3:
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:
Could you please clarify how you adding rows? Hopefully using model, right? Once new row added you have to call model's method fireTableDataChanged/not the best option/ or fireTableRowsInserted/better/ And dont forget to do it using SwingUtilities.invokeLater to avoid problems Swing
回答5:
Also when trying to update a model of JTable
, its important to remove any tableModelListener
before updating the model. I saw this observation with model.addColumn()
and table.moveColumn()
. Make sure you add the tableModelListener
after whatever changes gets made to the model.
回答6:
I hope you know that Swing is not thread safe(with few exceptions) . You need to take care of that in your code.
来源:https://stackoverflow.com/questions/13407418/threads-and-jtable