Why is my re-rendering of the JTable causing a stack overflow when I select the first row?
So I am trying to write an interface in swing. In short, I have a JTable where I listen for selection events and after the user selects an item, the code takes a little path through the code, after which it calls the "redraw" table; it empties the table and adds rows again.
This process seems to be fine for clicking on lines 2-4 (see code below), but when I click on the first line, I get a stack overflow that I cannot explain.
I know this is not exactly the best solution, since the table practically does not require redrawing, but I would first of all want my code to be clean and logically structured (which is what causes the redraw), and second I was trying to get what causes this for so long that I really wanted to know what was going on.
Here is a runnable class that reproduces the problem:
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
public class Tester implements ListSelectionListener {
private DefaultTableModel model;
public Tester(DefaultTableModel model) {
this.model = model;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(200, 200);
frame.setVisible(true);
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel();
table.setModel(model);
table.getSelectionModel().addListSelectionListener(new Tester(model));
model.setColumnCount(3);
model.setColumnIdentifiers(new String[]{"col1", "col2", "col3"});
frame.add(table);
model.addRow(new Object[]{"1", "2", "3"});
model.addRow(new Object[]{"4", "2", "3"});
model.addRow(new Object[]{"3", "2", "3"});
model.addRow(new Object[]{"2", "2", "3"});
}
public void valueChanged(ListSelectionEvent event) {
model.setRowCount(0);
model.addRow(new Object[]{"1", "2", "3"});
model.addRow(new Object[]{"4", "2", "3"});
model.addRow(new Object[]{"3", "2", "3"});
model.addRow(new Object[]{"2", "2", "3"});
}
}
source to share
The reason for stackoverflow is that when you delete all lines and start adding lines, you start the listener again. I'm not a big fan of modifying the model in a select listener (think about a situation where another select listener is added to the table), it will get completely obfuscated events. A possible solution for this is at least using invokeLater
).
But to avoid stackoverflow exception use
@Override
public void valueChanged(ListSelectionEvent event) {
ListSelectionModel listSelectionModel = ( ListSelectionModel ) event.getSource();
listSelectionModel.removeListSelectionListener( this );
model.setRowCount(0);
model.addRow(new Object[]{"1", "2", "3"});
model.addRow(new Object[]{"4", "2", "3"});
model.addRow(new Object[]{"3", "2", "3"});
model.addRow(new Object[]{"2", "2", "3"});
listSelectionModel.addListSelectionListener( this );
}
source to share