TableView从排序中排除底行(总计)

我有一个简单的TableView(Java FX 2.0,但我认为问题相当通用),它获得了默认的排序function。 然而,该表在其最后一行中有一个总数,所以我想从排序算法中排除最后一行。

我找到了一个Swing JTable的解决方案,它包括为总行创建一个单独的表 – 可以转换为TableView,但它看起来有点麻烦。 我已经尝试实现我自己的比较器,但我认为不可能创建一个既可以升序也可以降序的命令。

根据lolsvemir的回答,我成功地使用自定义Comparator实现了“TOTAL”。 我使用column的sortTypeProperty设置比较器: col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));

定制比较器:

 public class BigDecimalColumnComparator implements Comparator { private final ObjectProperty sortTypeProperty; public BigDecimalColumnComparator(ObjectProperty sortTypeProperty) { this.sortTypeProperty = sortTypeProperty; } @Override public int compare(BigDecimal o1, BigDecimal o2) { TableColumn.SortType sortType = sortTypeProperty.get(); if (sortType == null) { return 0; } if (o1 instanceof TotalBigDecimal) { if (sortType == TableColumn.SortType.ASCENDING) { return 1; } else { return -1; } } else if (o2 instanceof TotalBigDecimal) { if (sortType == TableColumn.SortType.ASCENDING) { return -1; } else { return 1; } } return o1.compareTo(o2); } } 

使用JavaFX 8,可以定义排序策略,并且问题更容易修复。 假设包含总计的行是TOTAL

 table.sortPolicyProperty().set(t -> { Comparator comparator = (r1, r2) -> r1 == TOTAL ? 1 //TOTAL at the bottom : r2 == TOTAL ? -1 //TOTAL at the bottom : t.getComparator() == null ? 0 //no column sorted: don't change order : t.getComparator().compare(r1, r2); //columns are sorted: sort accordingly FXCollections.sort(t.getItems(), comparator); return true; }); 

如果你总是在Comparator的compareTo()方法中返回0? 这意味着所有元素“都是相同的”并且不应该发生交换的地方?

我有同样的问题,并且由于TableView属性调用单元工厂的行数与表中可见的行数不同,而且不仅仅是对于由TableView.setItems()方法设置的列表大小的行索引,IMO它是最好直接由单元工厂为每个需要它的列设置汇总值。

以下是此类单元工厂类的简单示例:

 public class LocalDateTableCell implements Callback, TableCell> { @Override public TableCell call(TableColumn p) { TableCell cell = new TableCell() { @Override protected void updateItem(LocalDate item, boolean empty) { super.updateItem(item, empty); if (item == null || empty) { setText(null); } else { setText(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) .format(item)); } if (getTableView().getItems().size() == getIndex()) setText("Test"); // This shows in the summary row } }; return cell; } } 

这种方法的优点是这样的行根本不涉及排序(因为它不在表项列表中)并且也不可选择。 此外,重写TableRow工厂很容易为整个摘要行设置不同的背景颜色,并将其与其他行区分开来。

但是,在向下滚动时,此附加行将不可见,因为TableView滚动实现不知道附加行,并且仅滚动到视口底部的项目列表中的最后一行。 这可以通过重写TableViewSkin.getItemCount()方法来解决,如下例所示。 不必覆盖TableView本身,但建议经常使用此类表。

 public class MyTableViewSkin extends TableViewSkin { private TableView tableView; public MyTableViewSkin(final TableView tableView) { super(tableView); this.tableView = tableView; } @Override public int getItemCount() { return tableView.getItems() == null || tableView.getItems().size() == 0 ? 0 : tableView.getItems().size() + 1; } } public class MyTableView extends TableView { public MyTableView() { super(); setSkin(new MyTableViewSkin<>(this)); } } 

这可能看起来像一个黑客,但就像一个魅力。