In my Java 8 app I use a SwingWorker
to get some data from a database and call publish
once I know the data for a full row that I then want to add to my table:
DefaultTableModel dtm123 = (DefaultTableModel) myTable.getModel();
@Override
protected void process(List<Integer> chunks) {
if(chunks!=null) {
ListIterator<Integer> li = chunks.listIterator();
while(li.hasNext()) {
dtm123.addRow(myDataList.get(li.next()).getRowArray());
}
}
}
dtm123.getRowCount()
is increased every time (I checked) but the table isn't updated to actually show the new rows. I tried to update it manually, which didn't work either:
dtm123.fireTableRowsInserted(0, dtm123.getColumnCount()-1);
Here's the weird thing: If I use the full version, it's filling the table just fine:
((DefaultTableModel) myTable.getModel()).addRow(myDataList.get(li.next()).getRowArray());
Can you not use the shorter version for filling a table? dtm123
isn't used anywhere else, so what's the difference between the two versions?
Edit:
Filling it directly like this (without the SwingWorker
) works:
myTable.setModel(new DefaultTableModel(
new Object[][] {},
new Object[] {"blaA","blaB","blaC"}
));
DefaultTableModel dtm123 = (DefaultTableModel) myTable.getModel();
dtm123.addRow(new String[] {"bla1A","bla1B","bla1C"});
dtm123.addRow(new String[] {"bla2A","bla2B","bla2C"});
dtm123.addRow(new String[] {"bla3A","bla3B","bla3C"});
dtm123.addRow(new String[] {"bla4A","bla4B","bla4C"});
dtm123.addRow(new String[] {"bla5A","bla5B","bla5C"});
dtm123.addRow(new String[] {"bla6A","bla6B","bla6C"});
dtm123.addRow(new String[] {"bla7A","bla7B","bla7C"});
Looks like the SwingWoker
is the problem but why? process
is running on the main thread, which has to be used for UI updates, and there are no exceptions or error messages.
Fixed it - there were two reasons why it didn't work:
Setting the model of a table (myTable.setModel(new DefaultTableModel(...add info here...));
) and creating the columns has to be done on the main/UI thread too.
process
is called at a seemingly random point in time after calling publish()
and there's no way to tell beforehand how many chunks there will be (could be just one or all of them), so you have to make sure that you get the DefaultTableModel
after you set up the columns. To guarantee this, either set up the columns before you call publish()
the first time (but still outside doInBackground
- see 1.) or call publish
for a "zeroth" time to set them up (see code below). In hindsight this seems pretty obvious...
If you're using a SwingWorker
like me, you can do something along the lines of:
DefaultTableModel dtm123;
@Override
protected void process(List<Integer> chunks) {
if(chunks!=null) {
ListIterator<Integer> li = chunks.listIterator();
int next;
while(li.hasNext()) {
next = li.next();
if(next==-1) {
//Set up columns/column titles here
myTable.setModel(new DefaultTableModel(
new Object[][] {},
columnHeaderArray
));
dtm123 = (DefaultTableModel) myTable.getModel();
} else {
//Add new rows here
dtm123.addRow(myDataList.get(next).getRowArray());
}
}
}
}
Use publish
as usual but once you know the columns' titles, call publish(-1)
to set them up (of course, before you add the rows).