In the example, I'm seeking to add a table to my GUI and then dynamically add rows to it (to show the progress). What I don't understand is why all the rows are appearing at once. I mean, the the table's changing, isn't it? Can someone please give me an explanation?
import java.awt.Component;
public class Main {
public static void main(String[] args) {
// Show GUI
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
GUI gui = new GUI();
gui.setVisible(true);
DefaultTableModel model = new DefaultTableModel(
new String[] { "Column 1", "Column 2" }, 0);
JTable table = new JTable(model);
gui.add(table);
gui.validate();
for (int i = 0; i < 10; i++) {
System.out.println("Row " + i);
model
.addRow(new String[] { "Row", String.valueOf(i) });
// model.fireTableDataChanged();
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
class GUI extends JFrame {
private static final long serialVersionUID = 1L;
public GUI() {
setTitle("GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 350, 100);
setLocationRelativeTo(null);
JPanel cp = new JPanel();
cp.setBorder(new EmptyBorder(10, 10, 10, 10));
setContentPane(cp);
}
}
As pointed out by kleopatra and peeskillet, my initial example suffered from a stupid mistake. It's worth noting that peeskillet and I were following different approaches, though. In my example, the columns meant to represent connection attempts (more or less) that can take an unknown amount of time and that can actually fail (in that case, and only in that case, the next column would come into play and so on). Therefore, it wouldn't have made sense for me to add the rows at once (which was probably what made my example look weird to peeskillet). I've solved the task using a SwingWorker. As pointed out by kleopatra, there was a another mistake, which is now fixed. Here's my code:
package SwingWorkerExampleCopy;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.BorderLayout;
public class SwingWorkerExampleCopy {
public static void main(String[] args) {
// Show GUI
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
GUI gui = new GUI();
DefaultTableModel tableModel = new DefaultTableModel();
// Use a SwingWorker
Worker worker = new Worker(tableModel);
worker.execute();
JTable table = new JTable(tableModel);
table.setEnabled(false);
// table.setTableHeader(null);
JScrollPane scrollPane = new JScrollPane(table);
gui.getContentPane()
.add(scrollPane, BorderLayout.CENTER);
}
});
}
}
class GUI extends JFrame {
private static final long serialVersionUID = 1L;
public GUI() {
setTitle("GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 350, 400);
setLocationRelativeTo(null);
setVisible(true);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
}
}
class Worker extends SwingWorker<DefaultTableModel, Object[]> {
private final static int numRows = 10;
private final static int numCols = 10;
private DefaultTableModel model;
Worker(DefaultTableModel model) {
this.model = model;
model.setColumnCount(numCols);
}
@Override
protected DefaultTableModel doInBackground() throws Exception {
// Add row
for (int row = 0; row < numRows; row++) {
// Build columns
for (int col = 0; col < numCols; col++) {
if (col == 0) {
publish(new Object[] { new String("Row " + row), row,
col });
} else {
// Simulate a slow source
Thread
.sleep(new Random().nextInt((250 - 50) + 1) + 50);
Boolean isSuccessful = false;
// Simulate a return value
if (new Random().nextBoolean()) {
isSuccessful = true;
}
publish(new Object[] {
new String((isSuccessful == true ? "x" : "o")), row,
col });
if (isSuccessful == true) {
break;
}
}
}
}
return model;
}
@Override
protected void process(List<Object[]> chunks) {
for (Object[] chunk : chunks) {
// chunk[0]: cell value
// chunk[1]: number
// chunk[2]: column
if ((int) chunk[2] == 0) {
Object[] row = new Object[numCols];
row[0] = (Object) chunk[0];
model.addRow(row);
} else {
model.setValueAt((Object) chunk[0], (int) chunk[1],
(int) chunk[2]);
}
}
}
}