Domanda

Ho un semplice tavolo da tavolo (Java FX 2.0, ma suppongo che il problema sia abbastanza generico) che ottiene la funzione di ordinamento predefinita.Tuttavia, il tavolo ha un totale nella sua ultima riga, quindi vorrei escludere quell'ultima riga dall'algoritmo di ordinamento.

Ho trovato una soluzione per un jtable swing che consiste in Creazione di una tabella separata per la riga totale - sarebbe trasplicabile a un tableview ma sembra un po 'ingombrante.Ho provato ad implementare il mio comparatore ma non penso che sia possibile crearne uno che funzionerebbe sia negli ordini ascendenti e discendenti.

È stato utile?

Soluzione

Con JAVAFX 8 è possibile definire una politica di ordinamento e il problema è più facile da risolvere.Supponendo che la riga contenente i totali sia 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;
});
.

Altri suggerimenti

Basato sulla risposta di Lolsvemir implementa con successo un "totale" con un comparatore personalizzato. Ho impostato il comparatore con la sorristino della colonna: col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));

Comparatore personalizzato:

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

E se ritorni sempre 0 nel metodo del confronto del tuo comparatore ()?Significa che tutti gli elementi "sono gli stessi" e non dovrebbe verificarsi uno scambio di luoghi?

Ho avuto lo stesso problema e, a causa della proprietà TableView per chiamare la fabbrica di celle per tutte le righe come sono visibili nella tabella, e non solo per gli indici di riga fino alla dimensione dell'elenco impostata da TableView.setems (), IMO È meglio impostare il valore di sintesi direttamente dalla fabbrica cella per ogni colonna che deve averla.

Ecco il semplice esempio di tale classe di cella di fabbrica:

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

I vantaggi di questo approccio sono che tale riga non è coinvolta nell'ordinamento (perché non è nell'elenco degli articoli da tavolo) e non selezionabile anche. Inoltre, con la fabbrica di tablerow overringing è facile da impostare un colore di sfondo diverso per un'intera riga riassuntiva e per distinguerlo da altre righe.

Tuttavia, questa riga aggiuntiva non sarà visibile durante lo scorrimento verso il basso perché l'implementazione dello scorrimento della tabella non sa per la riga aggiuntiva e scorrerà solo verso l'ultima riga dall'elenco degli articoli nella parte inferiore della vista. Che può essere risolto ignorando il metodo tableviewskin.getitemcount (), come nell'esempio seguente. Il tableview sovrascrittura non è necessario, ma è consigliato se tale tabella viene utilizzata spesso.

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

Questo può sembrare un hack, ma funziona come un fascino.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top