Question

J'ai un simple TableView (Java FX 2.0, mais je suppose que le problème est assez générique) qui obtient la fonctionnalité de tri par défaut.Cependant, le tableau a un total dans sa dernière ligne, je voudrais donc exclure cette dernière ligne de l'algorithme de tri.

J'ai trouvé une solution pour une Swing JTable qui consiste à créer un tableau séparé pour la ligne totale - cela serait transposable à un TableView mais cela semble un peu fastidieux.J'ai essayé d'implémenter mon propre comparateur mais je ne pense pas qu'il soit possible d'en créer un qui fonctionnerait à la fois par ordre croissant et décroissant.

Était-ce utile?

La solution

Avec JavaFX 8, il est possible de définir une politique de tri et le problème est plus facile à résoudre.En supposant que la ligne contenant les totaux est 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;
});

Autres conseils

Sur la base de la réponse de lolsvemir, j'implémente avec succès un "TOTAL" avec un comparateur personnalisé.J'ai défini le comparateur avec le sortTypeProperty de la colonne :col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));

Comparateur personnalisé :

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

et si vous retournez toujours 0 dans la méthode comparaison de la comparaison ()?Cela signifie que tous les éléments "sont les mêmes" et aucun échange de lieux devrait se produire?

J'avais le même problème et, en raison de la propriété TableView pour appeler l'usine de cellule pour autant de lignes que visibles dans la table, et non seulement pour les indices de ligne jusqu'à la taille de la liste définie par la méthode TableView.settems (), IMO Il est préférable de définir une valeur sommaire directement par l'usine de cellule pour chaque colonne qui doit l'avoir.

Voici l'exemple simple de cette classe d'usine de cellule:

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

Avantages de cette approche sont que cette ligne n'est pas impliquée du tout (car elle n'est pas dans la liste des articles de table) et non sélectionnable également. De plus, avec une usine de Tablerow Weddriding est facile à définir une couleur de fond différente pour une rangée de résumé entière et de la distinguer des autres lignes.

Cependant, cette ligne supplémentaire ne sera pas visible lors du défilement, car la mise en œuvre du défilement de la tableView ne connaît pas la ligne supplémentaire et ne saura que sur la dernière ligne de la liste des articles au bas de la fenêtre. Cela peut être résolu par la méthode de la tableviewskin.getemcount (), comme dans l'exemple suivant. La table remplaçable elle-même n'est pas nécessaire, mais est recommandée si cette table est souvent utilisée.

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

Cela peut ressembler à un piratage, mais fonctionne comme un charme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top