java - 单击 JTable 标题时排序错误的列

标签 java swing sorting jtable jtableheader

我有以下代码用于 RowSorterListener。这样做的目的是在不影响任何其他列的情况下对列进行排序。

import javax.swing.event.RowSorterListener;
import javax.swing.event.RowSorterEvent;
import javax.swing.JTable;
import javax.swing.RowSorter.SortKey;
import java.util.List;
import java.util.Arrays;

public class UnrelateData implements RowSorterListener {
    JTable table;
    int columnSorted = -1;
    Object[][] dataStore;

    public UnrelateData(JTable table) {
        this.table = table;
    }

    @Override
    public void sorterChanged(RowSorterEvent e)
    {
        if(e.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) {
            List<SortKey> keys = e.getSource().getSortKeys();
            for (SortKey key : keys) {
                if (key.getColumn() == -1) {
                    columnSorted = -1;
                    break;
                } else {
                    columnSorted = key.getColumn();
                    break;
                }
            }
            dataStore = getData();
        }

        if(e.getType() == RowSorterEvent.Type.SORTED) {
            List<SortKey> keys = e.getSource().getSortKeys();
            for (SortKey key : keys) {
                if (key.getColumn() == -1) {
                    columnSorted = -1;
                    break;
                } else {
                    columnSorted = key.getColumn();
                    break;
                }
            }

            for(int i = 0; i < table.getColumnCount(); i++) {
                if(i != columnSorted && columnSorted != -1) {
                    for (int j = 0; j < table.getRowCount(); j++) {
                        table.setValueAt(dataStore[i][j], j, i);
                    }
                }
            }
        }
    }

    private Object[][] getData() {
        int columnCount = table.getColumnCount();
        int rowCount = table.getRowCount();
        Object[][] tempData = new Object[columnCount][rowCount];

        for(int i = 0; i < columnCount; i++) {
            for(int j = 0; j < rowCount; j++) {
                tempData[i][j] = table.getValueAt(j, i);
            }
        }

        return tempData;
    };
}

这很好用。但是,有一个主要故障。如果一列被移动并且我尝试对一列进行排序,它不会正确地对该列进行排序。相反,它会在移动列的原始位置错误地对该列进行排序。

Column 2 and 3 switched

虽然它应该看起来像(“第 1 列”和“第 2 列”保持未排序)

Column 2 and 3 switch properly

有人能解释为什么会发生这种情况以及如何解决吗?

注意:我不想使用 JTableHeader.reorderingAllowed(false)

编辑

我在我的代码中添加了以下 for 循环并尝试了不同的变体,但它似乎不起作用

尝试 1

if(e.getType() == RowSorterEvent.Type.SORTED) {
    int[] actualColumn = new int[table.getColumnCount()];
    for(int i = 0; i<table.getColumnCount(); i++){
        actualColumn[i] = table.convertColumnIndexToModel(i);
    }

    int[] actualRow = new int[table.getRowCount()];
    for(int i = 0; i<table.getRowCount(); i++){
        actualRow[i] = table.convertRowIndexToModel(i);
    }

    List<SortKey> keys = e.getSource().getSortKeys();
    for (SortKey key : keys) {
        if (key.getColumn() == -1) {
            columnSorted = -1;
            break;
        } else {
            columnSorted = key.getColumn();
            break;
        }
    }

    for(int i = 0; i < table.getColumnCount(); i++) {
        if(i != columnSorted && columnSorted != -1) {
            for (int j = 0; j < table.getRowCount(); j++) {
                table.setValueAt(dataStore[i][j], actualRow[j], actualColumn[i]);
            }
        }
    }
}

尝试 2

private Object[][] getData() {
    int columnCount = table.getColumnCount();
    int rowCount = table.getRowCount();

    int[] actualColumn = new int[columnCount];
    for(int i = 0; i<table.getColumnCount(); i++){
        actualColumn[i] = table.convertColumnIndexToModel(i);
    }

    int[] actualRow = new int[rowCount];
    for(int i = 0; i<table.getRowCount(); i++){
        actualRow[i] = table.convertRowIndexToModel(i);
    }

    Object[][] tempData = new Object[columnCount][rowCount];

    for(int i = 0; i < columnCount; i++) {
        for(int j = 0; j < rowCount; j++) {
            tempData[i][j] = table.getValueAt(actualRow[j], actualColumn[i]);
        }
    }

    return tempData;
};

尝试 3 是尝试 1 和尝试 2 的结合

最佳答案

  • RowSorterListener 中的代码指定用于正确返回索引(来自 RowSorterListener 的事件)

  • 默认情况下,您永远不需要知道 JTable View 中的顺序,所有这些事件都是模型事件

  • 添加 TableColumnModelListener 如果您想跟踪 columnMoved,所有以编程方式排序的事件都将绘制在 JTable 的 View 中正确

  • 第一。尝试不对列重新排序,

enter image description here

Column NO. - 0 is sorted
Column NO. - 1 is sorted
Column NO. - 2 is sorted
Column NO. - 3 is sorted
Column NO. - 4 is sorted

... and so on
BUILD SUCCESSFUL (total time: 21 seconds)

.

  • 第二。尝试对列进行重新排序(通过鼠标拖动)

enter image description here

.

Column NO. - 0 is sorted
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
Column NO. - 1 is sorted
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnSelectionChanged from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
Column NO. - 2 is sorted
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
columnMoved from ColumnModelListener
Column NO. - 3 is sorted
Column NO. - 4 is sorted
Column NO. - 0 is sorted
Column NO. - 1 is sorted
Column NO. - 2 is sorted
BUILD SUCCESSFUL (total time: 10 seconds)
  • 第三。如果 Swing Timer 未初始化且所有事件均由用户手工制作,则尝试相同的正确输出

  • 例如

.

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import javax.swing.*;
import javax.swing.RowSorter.SortKey;
import javax.swing.event.*;
import javax.swing.table.*;

public class SortTest1 {

    private JFrame frame = new JFrame(getClass().getSimpleName());

    private DefaultTableModel model = new DefaultTableModel(10, 5) {
        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };
    private JTable table = new JTable(model);
    private TableRowSorter<?> sorter;
    private static final Random rnd = new Random();
    private Timer timer;
    private int columnNo = 0;


    public SortTest1() {
        for (int row = model.getRowCount(); --row >= 0;) {
            int i = 20 + row % 20;
            model.setValueAt(row + " " + i, row, 0);
            model.setValueAt(i + row, row, 1);
            model.setValueAt(rnd.nextBoolean(), row, 2);
            model.setValueAt(rnd.nextDouble(), row, 3);
            model.setValueAt(row + " " + i * 1, row, 4);
        }
        table.setAutoCreateRowSorter(true);
        sorter = (TableRowSorter<?>) table.getRowSorter();
        sorter.setSortsOnUpdates(true);
        sorter.addRowSorterListener(new RowSorterListener() {

            @Override
            public void sorterChanged(RowSorterEvent rse) {
                if (rse.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) {
                    List<SortKey> keys = rse.getSource().getSortKeys();
                    for (SortKey key : keys) {
                        System.out.println("Column NO. - " + key.getColumn() + " is sorted");
                        if (key.getColumn() == 0) {
                            break;
                        } else {
                            break;
                        }
                    }
                }
            }
        });
        frame.add(new JScrollPane(table));
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
            // just handle columnMarginChanged to re-paint headings
            @Override
            public void columnMarginChanged(ChangeEvent e) {
                System.out.println("columnMarginChanged from ColumnModelListener");
            }

            @Override
            public void columnAdded(TableColumnModelEvent e) {
                System.out.println("columnAdded from ColumnModelListener");
            }

            @Override
            public void columnRemoved(TableColumnModelEvent e) {
                System.out.println("columnRemovedfrom ColumnModelListener");
            }

            @Override
            public void columnMoved(TableColumnModelEvent e) {
                System.out.println("columnMoved from ColumnModelListener");
            }

            @Override
            public void columnSelectionChanged(ListSelectionEvent e) {
                System.out.println("columnSelectionChanged from ColumnModelListener");
            }
        });
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        timer = new javax.swing.Timer(1000, updateCol());
        timer.setRepeats(true);
        timer.start();
    }

    private Action updateCol() {
        return new AbstractAction("Sort JTable") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (columnNo > 4) {
                    columnNo = 0;
                    sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(columnNo, SortOrder.ASCENDING)));              
                } else {
                    sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(columnNo, SortOrder.ASCENDING)));
                    columnNo++;
                }
            }
        };
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new SortTest1();
        });
    }
}

关于java - 单击 JTable 标题时排序错误的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34829921/

相关文章:

Java 进程在重负载下不会在 SIGTERM 上退出

java - 需要理解

c++ - 如何对数组中的字符串进行排序 C++

c - 如何在一个循环中对C中的数组进行排序?

java - 无法在 Spring Boot 2.2 中设置命令行配置文件

java - 如何检查我是否在 hibernate 中使用 c3p0?

java - 具有属性和文本内容的复杂类型的 JAXB 反编码

java - JFrame 的编程关闭

java - JDialog为主窗口时正确关闭java程序

java - 我不想更改方法内的数组