Tiny
Tiny

Reputation: 27899

Sorting data held by JTable after insertion

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.

enter image description here

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.

enter image description here

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

Answers (1)

Tom McIntyre
Tom McIntyre

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

Related Questions