TableView исключить нижний ряд (всего) от сортировки
Вопрос
У меня простая табличка (Java fx 2.0, но я полагаю, проблема довольно общего), которая получает функцию сортировки по умолчанию.Однако таблица имеет всего в его последней строке, поэтому я хотел бы исключить эту последнюю строку из алгоритма сортировки.
Я нашел решение для качания JTable, который состоит в Создание отдельной таблицы для полной строки - это было бы транспонировано в таблицу, но кажется немного громоздким.Я попытался реализовать свой собственный компаратор, но я не думаю, что можно создать один, который будет работать в заказах по возрастанию, так и по убыванию.
Решение
с javafx 8 можно определить политику сортировки, и проблема легче исправить.Предполагая, что строка, содержащая итоги, является TOTAL
:
table.sortPolicyProperty().set(t -> {
Comparator<Row> 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;
});
. Другие советы
На основании ответа Lolsvemir, я успешно реализует «всего» с пользовательским компаратором.
Я установил компаратор с столбцом sorttypeproperty:
col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));
Пользовательский компаратор:
public class BigDecimalColumnComparator implements Comparator<BigDecimal> {
private final ObjectProperty<TableColumn.SortType> sortTypeProperty;
public BigDecimalColumnComparator(ObjectProperty<TableColumn.SortType> 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);
}
}
. И если вы всегда возвращаете 0 в методе сравнения () вашего компаратора?Это означает, что все элементы «одинаковы», и не должно возникнуть замена мест?
У меня была такая же проблема, и, благодаря свойству TablView, чтобы позвонить в ячейку завод, как можно больше рядов, как видно в таблице, и не только для индексов строки до размера списка, установленного методом TableView.SetiTems (), ИМО лучше установить сводную ценность непосредственно по ячейке для каждого столбца, который должен иметь его.
Вот простой пример такого клеточного заводского класса:
public class LocalDateTableCell<T> implements
Callback<TableColumn<T, LocalDate>, TableCell<T, LocalDate>> {
@Override
public TableCell<T, LocalDate> call(TableColumn<T, LocalDate> p) {
TableCell<T, LocalDate> cell = new TableCell<T, LocalDate>() {
@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;
}
}
.
Преимущества этого подхода заключаются в том, что такой строк не участвует в сортировке вообще (потому что он не находится в списке элементов таблицы), а не выбирается. Кроме того, с переоцененной фабрикой стоала легко установить различный цвет фона для цельного сводка и отличить его от других рядов.
Однако этот дополнительный ряд не будет видимым при прокрутке, потому что реализация прокрутки TableView не знает для дополнительной строки и будет прокручивать только в последнюю строку из списка элементов в нижней части Viewport. Это может быть решено путем переопределения метода TableViewskin.geteTemcount (), как в следующем примере. Переопределение самой таблицы не нужно, но рекомендуется, если такая таблица используется часто.
public class MyTableViewSkin<T> extends TableViewSkin<T> {
private TableView<T> tableView;
public MyTableViewSkin(final TableView<T> 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<S> extends TableView<S> {
public MyTableView() {
super();
setSkin(new MyTableViewSkin<>(this));
}
}
.
Это может выглядеть как хак, но работает как очарование.