Preserve JTable selection across TableModel change
We're seeing JTable
selection get cleared when we do a fireTableDataChanged()
or fireTableRowsUpdated()
from the TableModel
.
Is this expected, or are we doing something wrong? I didn't see any property on the JTable
(or other related classes) about clearing/preserving selection on model updates.
If this is default behavior, is there a good way to prevent this? Maybe some way to "lock" the selection before the update and unlock after?
The developer has been experimenting with saving the selection before the update and re-applying it. It's a little slow.
This is Java 1.4.2 on Windows XP, if that matters. We're limited to that version based on some vendor code we use.
Asked by: Ada855 | Posted: 28-01-2022
Answer 1
You need to preserve the selection and then re-apply it.
First of all you will need to get a list of all the selected cells.
Then when you re-load the JTable with the new data you need to programmatically re-apply those same selections.
The other point I want to make is, if the number or rows or columns in your table are increasing or decreasing after each table model reload, then please don't bother preserving the selection.
The user could have selected row 2 column 1 having a value say "Duck", before model updation. But after model updation that same data can now occur in row 4 column 1, and your original cell row 2 column 1 could have new data such as "Pig". Now if you forcibly set the selection to what it was before the model updation, this may not be what the user wanted.
So programmatically selecting cells could be a double edged sword. Don't do it, if you are not sure.
Answered by: Lily157 | Posted: 01-03-2022Answer 2
You can automatically preserve a table's selection if the STRUCTURE of that table hasn't changed (i.e. if you haven't add/removed any columns/rows) as follows.
If you've written your own implementation of TableModel, you can simply override the fireTableDataChanged() method:
@Override
public void fireTableDataChanged() {
fireTableChanged(new TableModelEvent(this, //tableModel
0, //firstRow
getRowCount() - 1, //lastRow
TableModelEvent.ALL_COLUMNS, //column
TableModelEvent.UPDATE)); //changeType
}
and this should ensure that your selection is maintained provided that only the data and not the structure of the table has changed. The only difference between this, and what would be called if this method weren't overridden is that getRowCount() - 1 is passed for the lastRow argument instead of Integer.MAX_VALUE, the latter of which acts a signifier that not only has all the data in the table changed but that the number of rows may have as well.
Answered by: Julian392 | Posted: 01-03-2022Answer 3
I had the same issue in an application. In my case the model in the table was a list of objects, where the object properties where mapped to columns. In that case, when the list was modified, I retrieved the selected index and stored the object that was selected before updating the list. After the list is modified and before the table is updated, I would calculate the position of the selected object. If it was still present after the modification, then I would set the selection to the new index.
Just setting the selected index in the table after the modification will not work, because the object may change position in the list.
As a side note, I found that working with GlazedLists makes life much easier when dealing with tables.
Answered by: John471 | Posted: 01-03-2022Answer 4
This is default behavior. If you call fireTableDataChanged()
the entire table is rebuild from scratch as you set entirely new model. In this case the selection is, naturally, lost. If you call fireTableRowsUpdated()
the selection is also cleared in general cases. The only way is to remember selection and then set this. Unfortunately there is no guarantee that the selection will be still valid. Be careful if restoring selection.
Answer 5
for reference, as @Swapnonil Mukherjee stated, this did the trick with a table with selectable rows:
// preserve selection calling fireTableDataChanged()
final int[] sel = table.getSelectedRows();
fireTableDataChanged();
for (int i=0; i<sel.length; i++)
table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);
Answered by: Thomas207 | Posted: 01-03-2022
Answer 6
If I recall correctly, saving selection and re-applying it is what we have done too...
Answered by: Max417 | Posted: 01-03-2022Answer 7
I was facing same issue and when tried to search the reason I got this question but it seems a bug in Java SDK. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786
WORK AROUND
A temporary work-around is available. It should be removed once this bug is fixed as it's suitability has NOT been tested against fixed releases.
Use this subclass of JTable.
Note: This is for the MetalLookAndFeel. If using other look and feels, the inner FixedTableUI subclass will have to extend the TableUI subclass for that look and feel.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
public class FixedTable extends JTable {
private boolean isControlDownInDrag;
public FixedTable(TableModel model) {
super(model);
setUI(new FixedTableUI());
}
private class FixedTableUI extends BasicTableUI {
private MouseInputHandler handler = new MouseInputHandler() {
public void mouseDragged(MouseEvent e) {
if (e.isControlDown()) {
isControlDownInDrag = true;
}
super.mouseDragged(e);
}
public void mousePressed(MouseEvent e) {
isControlDownInDrag = false;
super.mousePressed(e);
}
public void mouseReleased(MouseEvent e) {
isControlDownInDrag = false;
super.mouseReleased(e);
}
};
protected MouseInputListener createMouseInputListener() {
return handler;
}
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (isControlDownInDrag) {
ListSelectionModel rsm = getSelectionModel();
ListSelectionModel csm = getColumnModel().getSelectionModel();
int anchorRow = rsm.getAnchorSelectionIndex();
int anchorCol = csm.getAnchorSelectionIndex();
boolean anchorSelected = isCellSelected(anchorRow, anchorCol);
if (anchorSelected) {
rsm.addSelectionInterval(anchorRow, rowIndex);
csm.addSelectionInterval(anchorCol, columnIndex);
} else {
rsm.removeSelectionInterval(anchorRow, rowIndex);
csm.removeSelectionInterval(anchorCol, columnIndex);
}
if (getAutoscrolls()) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
if (cellRect != null) {
scrollRectToVisible(cellRect);
}
}
} else {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
}
Note Curtsey to http://bugs.sun.com
Answered by: Freddie163 | Posted: 01-03-2022Similar questions
java - JTable Selection and TableModel
I am facing an issue with JTable and the TableModel associated with it. The problem here is that let's say if I make a row/rows selections on my JTable, I would like to get the particular row object from the TableModel and pass it somewhere. Does anyone know how to do this efficiently?
swing - JTable TableModel problem in Java
I can show my data in a JTable without a problem, but when I want to filter while my app is running, the JTable is not showing me data changes. I searched for it and found a class named TableModel but I can't write my AbstractTableModel. Can anyone show me how I can do this?
Personelz.Java
package deneme.persistence;
import java.beans.PropertyChangeListener;
import java.be...
swing - JDBC TableModel for a JTable in Java?
I want to display a database table as a JTable. I have never used JTable before so I googled JTable and TableModel.
With that googling, I am able to write my own custom TableModel which show data stored in
Object[][] data;
Now, I want to show my database table data into JTable. I searched that also and have got an idea of that but still confused about what should goes where in the...
java - HowTo Remove a Row in a JTable with a Custom TableModel
I've been reading posts similar to mine, and reading through the Java tutorial page but I just can't seem to get this working. I'm not sure if I'm missing something fundamental or not...
I have a custom table model below that I need to be able to delete rows from. The table is initialized empty and rows are ...
java - Need a function that adds a new record to TableItem using TableModel in J2ME
How to create dynamic table model in J2ME? like from arrays
i use kxml parser to parse my data and show that data in table.
Could you please give me directions? source code is welcome as well!!
my bean looks like this
public class FIDS {
private String FNo;
private String AirCraft;
private String OnDate;
private String Gate;
private String AirCompany;
private String ...
swing - Java: Possible to replace TableModel in an existing JTable?
Is it possible to replace the entire TableModel in an existing JTable or do I have to recreate the JTable?
Java: serialize TreeModel, TableModel to JSON, and vice versa?
On the client side, a user specified input creates a unique TreeModel and TableModel.
This needs to be serialized to JSON for storage on MongoDB (stores JSON document directly).
The JSON needs to be parsed back into a TreeModel or TableModel which will be rendered again on the client side software.
Any library or existing codes which can faciliate this?
java - Getting JTable from its TableModel
I have a function which triggers with:
public void tableChanged(TableModelEvent e){...}
I got the TableModel from the TableModelEvent with:
TableModel model = (TableModel)e.getSource();
But I need the JTable to use it in a TablecellBalloonTip cosntructor. How can i get the JTable from the TableModel?
java - Is there a generic TableModel we can use in JTables?
I'm now looking into JTables and have a bunch of business objects that I retrieve from the DB with Hibernate + Spring Data JPA.
I love that Spring Data JPA handles all the cumbersome implementation of the DAL and was wondering if there's something similar for TableModel.
Basically, I would have something along the lines of...
java - How to set TableModel as DataSource in an empty iReport (NetBeans 7.1)
This is my first time to create a report using iReport plugin in Netbeans 7.1. I have all the records that I need (records were stored in a TableModel) and I want it to set as the datasource to an empty report.
Here's what I did so far:
1.) I have a TableModel from a ResultSet. (fields: Stu...
java - JTable from TableModel - add Buttons to each row
I have a school project where I need to create a gui for a database. The database contains 3 tables:
a table for pizzas
a table for toppings
And a table, which contains the foreign keys for the pizzas and toppings. Basically this table declares, what toppings does a pizza have.
I can display now the pizza table in a JTable through a custom
Still can't find your answer? Check out these amazing Java communities for help...
Java Reddit Community | Java Help Reddit Community | Dev.to Java Community | Java Discord | Java Programmers (Facebook) | Java developers (Facebook)