Ho cercato questo problema quando stavo cercando di implementare un riquadro di scorrimento cinetico simile al rotellina della mela. Le voci nel TreeSet
sono questa classe:
/**
* Data object that contains a {@code DoubleExpression} bound to an item's
* relative distance away from the current {@link ScrollPane#vvalueProperty()} or
* {@link ScrollPane#hvalueProperty()}. Also contains the item index of the
* scrollable content.
*/
private static final class ItemOffset implements Comparable<ItemOffset> {
/**
* Used for floor or ceiling searches into a navigable set. Used to find the
* nearest {@code ItemOffset} to the current vValue or hValue of the scroll
* pane using {@link NavigableSet#ceiling(Object)} or
* {@link NavigableSet#floor(Object)}.
*/
private static final ItemOffset ZERO = new ItemOffset(new SimpleDoubleProperty(0), -1);
/**
* The current offset of this item from the scroll vValue or hValue. This
* offset is transformed into a real pixel length of the item distance from
* the current scroll position.
*/
private final DoubleExpression scrollOffset;
/** The item index in the list of scrollable content. */
private final int index;
ItemOffset(DoubleExpression offset, int index) {
this.scrollOffset = offset;
this.index = index;
}
/** {@inheritDoc} */
@Override
public int compareTo(ItemOffset other) {
double d1 = scrollOffset.get();
double d2 = other.scrollOffset.get();
if (d1 < d2) {
return -1;
}
if (d1 > d2) {
return 1;
}
// Double expression has yet to be bound
// If we don't compare by index we will
// have a lot of values ejected from the
// navigable set since they will be equal.
return Integer.compare(index, other.index);
}
/** {@inheritDoc} */
@Override
public String toString() {
return index + "=" + String.format("%#.4f", scrollOffset.get());
}
}
Il DoubleExpression
può prendere un momento di essere vincolato in un compito runLater della piattaforma JavaFX, questo è il motivo per cui l'indice è incluso in questa classe wrapper.
Poiché lo scrollOffset
cambia in base alla posizione di scorrimento dell'utente sulla rotella di scorrimento, è necessario un aggiornamento. Solitamente l'ordine è sempre lo stesso, poiché l'offset è relativo alla posizione dell'indice dell'oggetto. L'indice non cambia mai, ma l'offset può essere negativo o positivo a seconda della distanza relativa degli articoli dalla proprietà vValue o hValue corrente di ScrollPane
.
Per aggiornare su richiesta solo quando necessario, è sufficiente seguire la guida della risposta sopra riportata di Tucuxi.
ItemOffset first = verticalOffsets.first();
verticalOffsets.remove(first);
verticalOffsets.add(first);
dove verticalOffsets è un TreeSet<ItemOffset>
. Se esegui una stampa del set ogni volta che viene chiamato questo snippet di aggiornamento, vedrai che è stato aggiornato.
+1 bella domanda – skaffman
Questa è solo curiosità morbosa, o stai cercando un beneficio specifico, diciamo in termini di prestazioni o semplicità del codice? – greim
Stavo cercando un modo semplice e non invasivo per mantenere l'ordinamento di una raccolta mentre gli eventi aggiornano gli oggetti al suo interno. Alterare l'appartenenza ha effetti collaterali su altri consumatori della collezione. IMO, l'attivazione di un resort di un elemento sembra una funzionalità di base per una raccolta ordinata. Le interfacce grafiche – Stevko