TableViewのソートから最下行(合計)を除外します
質問
私は単純なTableview(Java FX 2.0を持っていますが、問題はかなり一般的なものであると思います)デフォルトのソート機能を取得します。ただし、テーブルの最後の行に合計があるため、ソートアルゴリズムからその最後の行を除外します。
私は全行の別のテーブルの作成で構成されるSwing Jtableのソリューションを見つけました - それはTableViewに転送可能であろうが、それは少し面倒なように思われる。私は自分の比較器を実装しようとしましたが、昇順と降順の両方で機能するものを作成することが可能であるとは思わない。
解決
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の答えに基づくカスタムコンパレータで「合計」を正しく実装しています。
Columberの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を返すならば?それはすべての要素 "が同じである"であり、場所の交換は起こるべきですか?
私は同じ問題を有し、TableViewプロパティにより、テーブル内に表示されているように、TableView.SetItems()メソッドで設定されたリストのサイズまでの行インデックスだけではなく、TableViewプロパティがテーブルに表示されます。 IMOそれを持つ必要があるすべての列について、Cell Factoryによって直接要約値を設定するのが良いです。
そのようなセルファクトリクラスの簡単な例:
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;
}
}
.
このアプローチの利点は、そのような行がまったくソートに関与していないことです(テーブル項目リストにはないため)、選択できない。さらに、TableRowファクトリをオーバーライドすることで、サマリー行全体に異なる背景色を設定し、他の行と区別するのが簡単です。
しかし、TableViewスクロール実装では追加行がわからず、ビューポートの下部の項目リストから最後の行にのみスクロールするため、この追加の行は表示されません。次の例のように、TableViewSkin.GetItemCount()メソッドをオーバーライドすることで解決できます。 TableView自体をオーバーライドする必要はありませんが、そのようなテーブルが頻繁に使用されている場合はお勧めです。
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));
}
}
.
これはハックのように見えるかもしれませんが、魅力のように動作します。