【问题标题】:Sorting JTable after adding rows添加行后对JTable进行排序
【发布时间】:2017-10-30 21:22:05
【问题描述】:

添加新行后我必须对JTable (Object[][] data, Object[] headers) 进行排序。

这是代码(不起作用)

public class Window extends JFrame {
    Window() {
        super();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JTable table = new JTable();
        table.setModel(new DefaultTableModel(null, new String[]{"col1"}));
        TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());
        sorter.setComparator(0, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        sorter.setSortsOnUpdates(true);
        table.setRowSorter(sorter);

        DefaultTableModel model = (DefaultTableModel)table.getModel();
        model.addRow(new String[] {"A"});
        model.addRow(new String[] {"C"});
        model.addRow(new String[] {"B"});

        this.getContentPane().add(table);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        new Window();
    }
}

输出结果:表(A,C,B),预期(A,B,C)

模型 - DefaultTableModel
deviceTable - Jtable

【问题讨论】:

  • 为了获得最佳帮助,请创建并发布一个有效的minimal reproducible example -- 一个小程序,小到可以完全作为代码格式的文本在您的问题中发布,我们无需修改即可编译和运行,这向我们展示了您的问题。
  • @HovercraftFullOfEels 添加了 MCVE

标签: java database swing sorting jtable


【解决方案1】:

根据您的示例,您需要定义一个排序键,否则该表实际上是未排序的...

List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(sortKeys);
table.setRowSorter(sorter);

以下示例(基于您的示例)对第一列进行排序。当您点击按钮时,它会添加行,然后对其进行排序

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                JTable table = new JTable();
                table.setModel(new DefaultTableModel(null, new String[]{"col1"}));
                TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());
                sorter.setComparator(0, new Comparator<String>() {
                    @Override
                    public int compare(String o1, String o2) {
                        return o1.compareTo(o2);
                    }
                });
                sorter.setSortsOnUpdates(true);
                List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
                sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
                sorter.setSortKeys(sortKeys);
                table.setRowSorter(sorter);

                JButton btn = new JButton("...");
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        DefaultTableModel model = (DefaultTableModel) table.getModel();
                        model.addRow(new String[]{"A"});
                        model.addRow(new String[]{"C"});
                        model.addRow(new String[]{"B"});
                    }
                });

                frame.add(new JScrollPane(table));
                frame.add(btn, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

【讨论】:

  • 非常感谢!它确实有效,但只有视觉效果(当我选择行并调用 table.getSelectedRow() 时,它会返回旧位置)
  • 是的,RowSorter 进行“虚拟”排序,对随后在视图和模型之间映射的行索引进行排序。您需要使用JTable#convertRowIndexToModelJTable#convertRowIndexToView 在模型和视图之间进行转换。所有这些都包含在How to use tables, Sorting and Filtering 教程中 - 这意味着模型永远不会被修改
【解决方案2】:
model.fireTableDataChanged();

不要直接调用 fireXXX() 方法。

TableModel 负责调用适当的方法(在本例中为 fireTableRowsInserted)。

编辑:

摆脱创建排序器和比较器的代码。

您只需让表创建排序器。但是一旦你这样做了,你需要告诉排序器要排序哪一列:

table.setAutoCreateRowSorter(true);
((DefaultRowSorter)table.getRowSorter()).toggleSortOrder(0);

【讨论】:

  • 没用
  • 然后发布您的minimal reproducible example 来说明问题。因此,您首先使用硬编码数据进行测试以保持MCVE 完整,因为我们不需要访问您的自定义对象来证明添加数据时模型将自动排序。此外,不需要 revalidate() 和 repaint()。当模型改变时,Swing 组件会自动重新绘制自己。最后,为什么要使用自定义比较器?默认情况下将使用字符串比较器。
  • 如何通过默认字符串比较器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多