单击JTable Header时排序错误的列

我有一个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 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 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; }; } 

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

第2列和第3列已切换

而它应该看起来像(“第1列”和“第2列”保持未分类)

第2列和第3列正确切换

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

注意:我不想使用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 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是尝试一个和两个放在一起

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

  • 默认情况下,您永远不需要知道JTable视图的排序,所有这些事件都是models events

  • 在要跟踪columnMoved的情况下添加TableColumnModelListener ,以编程方式排序的所有事件都在JTable视图中正确绘制

  • 1。 没有列重新排序的attemtp,

在此处输入图像描述

 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) 

  • 第2位。 尝试使用列重新排序(通过鼠标拖动)

在此处输入图像描述

 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) 
  • 3。 如果没有初始化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 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(); }); } } 

从您的问题描述(未查看代码)您可能不会将从视图索引报告的索引转换为模型索引,反之亦然。

Cf JTable一般说明,引用相关部分:

类似地,当使用RowSorter提供的排序和过滤function时,底层的TableModel不需要知道如何进行排序,而是RowSorter将处理它。 当JTable与基础TableModel一起使用基于行的方法时,需要进行坐标转换。 所有JTables基于行的方法都是根据RowSorter ,它不一定与底层TableModel 。 例如,选择始终是JTable因此在使用RowSorter您需要使用convertRowIndexToViewconvertRowIndexToModel进行转换。 […]

您需要知道,表上的侦听器将在视图索引中报告,而不是模型索引。 如果使用视图索引从模型中获取值,您将遇到所描述的问题。

要处理这些转换,JTable中存在以下方法:

  • convertRowIndexToModel
  • convertRowIndexToView
  • convertColumnIndexToModel
  • convertColumnIndexToView

一个小例子,用于解释与您的问题相关的JTable中的模型与视图。 表的模型包含数据。 视图是屏幕上显示的内容。 视图将其列映射到模型中的列。 当列被拖动到视图中的不同位置时(即您在屏幕上看到的内容),您的模型不会更改(即数据容器中的数据不会更改)。 会发生什么是从视图到模型的映射更改。

例如,在数据模型中有三列A,B和C,并将屏幕上的第二列拖到第一个位置,以便屏幕上的顺序变为B,A,C。 视图的作用是更改其映射以在第一个位置显示列B,在第二个位置显示A,在第三个位置显示C. 所以映射是view:1->model:A, view:2->model:B, view:3->model:C和拖动后变为view:1->model:B, view:2->model:A, view:3->model:C

现在回到我之前说过的话。 当JTable上的任何侦听器报告索引(行,列)时,它使用视图索引。 现在,如果要查看模型中这些索引的值,首先需要使用我之前突出显示的方法将这些视图索引转换为模型索引。

因此,您始终需要了解您正在接收哪些索引以及您打算如何使用它们。 如果从表中接收索引(即视图)并且您希望使用这些索引在模型中查找值,则首先需要使用convertXXXToModel方法转换索引。