当表处于排序模式(使用 RowSorter
)时,似乎大多数时候表都是实时排序的。例如,每当我添加新行时,表格都会自动排序(编辑单元格除外)。我想知道是否有任何方法可以禁用这种实时排序行为。
我想做的是:在对表进行升序或降序排序后,排序器将保持当前的排序状态并停止实时排序。然后可以在底部添加新行,并且可以上下移动所选行,并且表格会更新视图模型中的所有更改。
@trashgod:谢谢你的回答。我实际上有点像本机行排序器方法,因为我可以在三态(升序、降序和未排序)中圈出列状态。如果使用 Collections.sort,我将不得不创建一个变量来保存原始行顺序,然后再每次对其进行排序。
Collections.sort()
和自定义Comparator
(如此处所示)对TableModel
的行进行排序,而RowSorter
可以接受指定排序方向的参数。
enum Sort { ASCENDING, DESCENDING; }
class RecordComparator implements Comparator<Record> {
public RecordComparator(Sort sort, ...) { ... }
}
似乎您想要的是能够对表进行排序,但随后能够在不更改表排序顺序的情况下添加更多行。即使有可能,您也必须重写DefaultRowSorter
和TableRowSorter
(两者的源代码都可用)。原因是当前实现旨在保持一致的排序顺序(不考虑何时添加行)。您可能无法扩展 TableRowSorter 来克服此问题,因为它的父类有很多与我刚刚描述的设计相关的私有函数。
我上面描述的是干净的方法。这是您可以执行此操作的另一种方法,每次要插入新行时都执行此操作:
-
将视图的当前排序顺序保存在地图中。我使用哈希图(
postion
)将排序列的第 i 行中的每个对象映射到它在视图中的位置。position.put(tableModel.getValueAt(i, column), sorter.convertRowIndexToView(i));
-
创建一个比较器,该比较器将使用上面创建的地图对传入数据进行排序。将 TableRowSorter 的列比较器设置为新创建的比较器。然后调用
sorter.sort()
,这是必需的DefaultRowSorter
因为需要缓存比较器。比较器将现有对象放在其当前位置,并将新对象(在插入期间创建)放在末尾。 -
在表模型中执行行插入。在我的代码中,我向表中的 3 列添加了 3 个随机整数、布尔值和双精度值。
-
通过将值设置为 null 来删除在 #3 中添加的比较器,
sorter.setComparator(sortKeys.get(0).getColumn(), null);
这样,下次在列上切换排序时,它将使用默认比较器而不是虚拟比较器。
完整的代码如下。它旨在每次按下按钮时向表中添加一行。请注意,我没有使用排序键> 1 或过滤器对此进行测试(我会把它留给你)。让我知道你对这个黑客的看法。
private void insertRowButtonActionPerformed(java.awt.event.ActionEvent evt) {
TableRowSorter<TableModel> sorter = (TableRowSorter<TableModel>)jTable1.getRowSorter();
final HashMap<Object, Integer> position = new HashMap<Object, Integer>();
List<? extends SortKey> sortKeys = sorter.getSortKeys();
if(!sortKeys.isEmpty()){
SortKey sortKey = sortKeys.get(0);
int column = sortKey.getColumn();
TableModel tableModel = sorter.getModel();
int n = sorter.getModelRowCount();
final SortOrder sortOrder = sortKey.getSortOrder();
for(int i=0;i<n;i++){
position.put(tableModel.getValueAt(i, column), sorter.convertRowIndexToView(i));
}
//add dummy comparator
sorter.setComparator(column, new Comparator<Object>(){
public int compare(Object o1, Object o2) {
int obj1Position = position.containsKey(o1) ? position.get(o1):position.size();
int obj2Position = position.containsKey(o2) ? position.get(o2):position.size();
return sortOrder == SortOrder.DESCENDING ? obj2Position - obj1Position:obj1Position - obj2Position;
}
});
sorter.sort();
}
/////////////insert row///////////////////
DefaultTableModel tableModel = (DefaultTableModel)jTable1.getModel();
tableModel.addRow(new Object[]{rand.nextInt(), rand.nextBoolean(), rand.nextDouble()});
/////////////end insert row///////////////
//remove dummy comparator
if(!sortKeys.isEmpty()){
sorter.setComparator(sortKeys.get(0).getColumn(), null);
}
}