Reputation: 27899
I populate a JTable
from a database. The data in JTable
is sorted based on the auto-generated primary key in descending order. The table looks like the following.
The data in the table is held by a list which contains a list of objects of a JPA entity - List<Country>
.
Since I display data in descending order by countryId
(primary key), the list needs to be sorted in descending by countryId
after data is inserted and before the fireTableRowsInserted(size, size)
method is executed.
After sorting this list in descending order by countryId
, the table looks wonky as follows.
Values through the given text fields are submitted after validation, when the given add button is pressed.
The row is added to database and to the list and the list is also sorted as mentioned but the data in the table are not shown as they are in the list.
See the last two rows in the preceding snap shot. The actual row which is created is not displayed. The last row is duplicated instead which is different from the underlying list where the new object is added and the list sorted too.
My AbstractTableModel
is as follows.
package admin.model;
import entity.Country;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public final class CountryAbstractTableModel extends AbstractTableModel
{
private List<Country> countries;
private List<String> columnNames;
public CountryAbstractTableModel(List<Country> countries)
{
this.countries = countries;
columnNames=getTableColumnNames();
}
//This is the method which sorts the list after adding a JPA entity object.
public void add(Country country)
{
int size = countries.size();
countries.add(country);
Comparator<Country> comparator = new Comparator<Country>()
{
@Override
public int compare(Country o1, Country o2)
{
return o2.getCountryId().compareTo(o1.getCountryId());
}
};
Collections.sort(countries, comparator);
fireTableRowsInserted(size, size);
}
@Override
public String getColumnName(int column)
{
return columnNames.get(column);
}
@Override
public Class<?> getColumnClass(int columnIndex)
{
switch (columnIndex)
{
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return String.class;
default:
return String.class;
}
}
private List<String> getTableColumnNames()
{
List<String> names = new ArrayList<>();
names.add("Index");
names.add("Id");
names.add("Country Name");
names.add("Country Code");
return names;
}
@Override
public int getRowCount()
{
return countries.size();
}
@Override
public int getColumnCount()
{
return 4;
}
public void remove(List<Long>list)
{
Iterator<Country> iterator = countries.iterator();
while(iterator.hasNext())
{
Country country = iterator.next();
Iterator<Long> it = list.iterator();
while(it.hasNext())
{
if(country.getCountryId().equals(it.next()))
{
iterator.remove();
int index = countries.indexOf(country);
fireTableRowsDeleted(index, index);
break;
}
}
}
}
@Override
public Object getValueAt(int rowIndex, int columnIndex)
{
Country country = countries.get(rowIndex);
switch (columnIndex)
{
case 0:
return rowIndex+1;
case 1:
return country.getCountryId();
case 2:
return country.getCountryName();
case 3:
return country.getCountryCode();
}
return "";
}
@Override
public void setValueAt(Object value, int rowIndex, int columnIndex)
{
Country country = countries.get(rowIndex);
if(value instanceof String)
{
String stringValue = value.toString();
switch(columnIndex)
{
case 2:
country.setCountryName(stringValue);
break;
case 3:
country.setCountryCode(stringValue);
break;
}
}
fireTableCellUpdated(rowIndex, columnIndex);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return columnIndex>1?true:false;
}
}
If I remove the given Comparator
as in the add()
method in the code snippet (i.e sorting is not done) then, the table is updated as it should be with the newly created row at the end of the table (which should be on top of the table. Hence sorting is necessary).
Why does this happen when the underlying list is sorted? (Again it doesn't happen, when the list is not sorted, it is left untouched.)
Upvotes: 1
Views: 971
Reputation: 3699
This is happening because you are telling the model that an element has been added at position 'size' (ie the last position in the list) but because you are sorting the list it is actually in the model at position 0 (in this example).
Probably the simplest way to fix this is to call fireTableDataChanged() and not worry about the index - I think your table would have to be pretty big for this to cause performance problems. Otherwise you could use list.indexOf() to find out where your new element ended up after sorting and call fireTableRowsInserted() with the correct indices.
Upvotes: 2