JTable row selection after TableModel update
How to preserve table row selecetion after table mode update (fireTableDataChanes)? I know that I should save selection before fire and restore it after (from there). But when I tr开发者_StackOverflowy to restore selection in TableModelListener it doesn't work. So where should I restore selection?
Update: Now I try to restore selection in this way: table.setModel(model);
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
table.addRowSelectionInterval(1, 1);
}
});
but it doesn't work.
This is an updated version of the first answer. You can use a field to store the row as it can be accessed by inner classes. I had some trouble with this solution tough because I used a periodic thread to update the table.
private int selectedRow = -1;
public void mymethod() {
//put code to create the table here...
JTable tableList = new JTable();
// Save selected row table
tableList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedRow = e.getFirstIndex();
}
});
// Restore selected raw table
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (selectedRow >= 0) {
tableList.addRowSelectionInterval(index, index);
}
}
});
}
});
}
Decision is simple: we should use Swing EventQueue:
final int selectedRow = 0;
// Save selected row table
tableList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedRow = e.getFirstIndex();
}
});
// Restore selected raw table
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (selectedRow >= 0) {
tableList.addRowSelectionInterval(index, index);
}
}
});
}
});
The example from the first answer shows the basic solution but won't work out of the box. It's not possible to change the final "selectedRow". So a mutable integer (e.g. AtomicInteger) should be used. The tamleModelListener dispatches to task to swing, so it gets invoked later - in most cases after the table change has already removed the selection. So selectedRow will in most cases be -1.
I have changed the above example a bit (and added single cell selection but it also works for full rows):
final AtomicInteger selectedRow=new AtomicInteger(-1);
final AtomicInteger selectedCol=new AtomicInteger(-1);
tblZeiten.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e)
{
selectedRow.set(tblZeiten.getSelectedRow());
selectedCol.set(tblZeiten.getSelectedColumn());
}
});
tblZeiten.getModel().addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e)
{
TableCellEditor editor=tblZeiten.getCellEditor();
if (editor!=null) editor.cancelCellEditing();
final int row=selectedRow.get();
final int col=selectedCol.get();
if (row<0||col<0) return;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// http://book.javanb.com/the-java-developers-almanac-1-4/egs/javax.swing.table/Sel.html
tblZeiten.changeSelection(row,col, false, false);
}
});
}
});
精彩评论