问题
Use case :
- an ordered ListView (or TableView)
- insertions are made after display
- updates of the keys are made after display
List at startup:
After adding 18:
After update:
As you can see nothing change!
The code:
public final class SortedListTest extends Application {
@Override
public void start( Stage stage ) throws Exception {
final ObservableList<IntegerProperty> il =
FXCollections.observableArrayList();
il.add( new SimpleIntegerProperty( 12 ));
il.add( new SimpleIntegerProperty( 24 ));
il.add( new SimpleIntegerProperty( 36 ));
final Button add = new Button( "Add 18" );
final Button update = new Button( "Update 24 to 8" );
final HBox ctrl = new HBox( 4.0, add, update );
final ListView<IntegerProperty> listVw =
new ListView<>( new SortedList<>( il, (l,r)-> l.get() - r.get()));
stage.setScene(
new Scene(
new BorderPane( listVw, ctrl, null, null, null ), 180, 120 ));
stage.show();
add.setOnAction( e -> {
il.add( new SimpleIntegerProperty( 18 ));
System.err.println( "--------------" );
il.stream().forEach( System.err::println );
});
update.setOnAction( e -> {
il.get( 1 ).set( 8 );
System.err.println( "--------------" );
il.stream().forEach( System.err::println );
});
}
public static void main( String[] args ) {
launch( args );
}
}
Console:
--------------
IntegerProperty [value: 12]
IntegerProperty [value: 24]
IntegerProperty [value: 36]
IntegerProperty [value: 18]
--------------
IntegerProperty [value: 12]
IntegerProperty [value: 8]
IntegerProperty [value: 36]
IntegerProperty [value: 18]
We can see the model is correctly updated but not the view, why?
Working Example
(After accepting the very simple but good answer of James_D:)
Here is a full sample with a record of properties to illustrate the solution:
public final class SortedListTest extends Application {
class Record {
final IntegerProperty _key = new SimpleIntegerProperty();
final StringProperty _value = new SimpleStringProperty();
Record( int k, String v ) {
_key .set( k );
_value.set( v );
}
@Override
public String toString() {
return "Key = " + _key.get() + ", value = " + _value.get();
}
}
@Override
public void start( Stage stage ) throws Exception {
final ObservableList<Record> il =
FXCollections.observableArrayList(
rec -> new Observable[]{ rec._key });
il.add( new Record( 12, "Douze" ));
il.add( new Record( 24, "Vingt quatre" ));
il.add( new Record( 36, "Trente six" ));
final Button add = new Button( "Add 18" );
final Button update = new Button( "Update 24 to 8" );
final HBox ctrl = new HBox( 4.0, add, update );
final SortedList<Record> sortedList =
il.sorted((l,r)-> Integer.compare(l._key.get(), r._key.get()));
final ListView<Record> listVw = new ListView<>( sortedList );
stage.setScene( new Scene(
new BorderPane( listVw, ctrl, null, null, null ), 200, 140 ));
stage.show();
add.setOnAction( e -> {
il.add( new Record( 18, "Dix huit" ));
System.err.println( "--------------" );
il.stream().forEach( System.err::println );
});
update.setOnAction( e -> {
il.get( 1 )._key.set( 8 );
System.err.println( "--------------" );
il.stream().forEach( System.err::println );
});
}
public static void main( String[] args ) {
launch( args );
}
}
And the result:
回答1:
The SortedList observes its underlying ObservableList. Thus it will only update its order if the underlying list fires change events.
For an observable list to fire update events when the state of one of its elements changes (as opposed to the list adding, removing, or reordering elements), it must be observing the corresponding properties. This won't happen unless you tell it to do so, using an extractor. The extractor is a function which maps an element in the list to an array of properties that should be observed: if those properties change the list will fire update events. In your scenario, where the list is the underlying list for a sorted list, this will allow the sorted list to reorder itself.
So you need to create your underlying list as
final ObservableList<IntegerProperty> il =
FXCollections.observableArrayList(
( IntegerProperty intProp ) -> new Observable[]{ intProp });
(ie. the property you want to observe is the element itself).
来源:https://stackoverflow.com/questions/27806814/javafx-sortedlist-listen-the-list-changes-and-the-list-items-updated-event