1

JTable我从数据库中填充一个。里面的数据JTable是根据自动生成的主键降序排列的。该表如下所示。

在此处输入图像描述

表中的数据由一个列表保存,该列表包含 JPA 实体的对象列表 - List<Country>

由于我按(主键)降序显示数据,因此在插入数据之后和执行方法之前countryId需要对列表进行降序排序。countryIdfireTableRowsInserted(size, size)

在按降序排序此列表后countryId,该表看起来很奇怪,如下所示

在此处输入图像描述

当按下给定的添加按钮时,通过给定文本字段的值在验证后提交。

该行已添加到数据库和列表中,并且列表也按上述方式排序,但表中的数据未显示为列表中的数据。

请参阅前面快照中的最后两行。不显示实际创建的行。最后一行是重复的,这与添加新对象并且列表也排序的基础列表不同。


AbstractTableModel的如下。

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;
    }
}

如果我删除了代码片段Comparator中的add()方法中的给定值(即未完成排序),则表将更新,因为它应该在表的末尾使用新创建的行(应该在表的顶部) .因此排序是必要的)。

为什么在对基础列表进行排序时会发生这种情况?(同样不会发生,当列表未排序时,它保持不变。)

4

1 回答 1

2

发生这种情况是因为您告诉模型一个元素已添加到位置“大小”(即列表中的最后一个位置),但是因为您正在对列表进行排序,它实际上在模型中的位置 0(在本例中) .

解决此问题的最简单方法可能是调用 fireTableDataChanged() 而不必担心索引 - 我认为您的表必须非常大才能导致性能问题。否则,您可以使用 list.indexOf() 找出排序后新元素的最终位置,并使用正确的索引调用 fireTableRowsInserted() 。

于 2013-09-14T21:32:02.540 回答