TableView excludes bottom row (total) from sorting

I have a simple TableView (Java FX 2.0, but I suppose the problem is pretty general) that gets the default sort function. However, the table has a total number in the last row, so I would like to exclude this last row from the sorting algorithm.

I found a Swing JTable solution that consists of creating a separate table for a common row - this will be transposed into the TableView, but it seems a little cumbersome, I tried to implement my own Comparator, but I don’t think that you can create one that will work like ascending and descending orders.

+3
source share
4 answers

With JavaFX 8, you can define a sort policy, and the problem is easier to fix. Assuming the line containing the totals is 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;
});
+3
source

Based on lolsvemir's answer, I successfully implement "TOTAL" with a custom Comparator. I set the comparator to the sortTypeProperty column: col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));

Custom Comparator:

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);
    }
}
+3
source

0 Comparator compareTo()? , "", ?

+2

, - TableView factory , , , TableView.setItems() , IMO, factory , .

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 factory .

However, this extra row will not be visible when scrolling down, because the TableView scrolling implementation does not know the extra row and will only scroll to the last row from the list of items at the bottom of the view window. This can be solved by overriding the TableViewSkin.getItemCount () method, as in the following example. An override of TableView is not required in itself, but is recommended if such a table is used frequently.

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));
  }
}

It may look like a hack, but it works like a charm.

+1
source

All Articles