JavaFX SortedList:监听列表更改和列表项更新事件

Aub*_*bin 1 java sorting javafx-8

使用案例:

  • 有序的ListView(或TableView)
  • 插入后显示
  • 在显示之后进行键的更新

启动时列表:

在启动时列出

添加18后:

加18后

更新后:

更新后

你可以看到没有任何变化!

代码:

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 );
   }
}
Run Code Online (Sandbox Code Playgroud)

安慰:

--------------
IntegerProperty [value: 12]
IntegerProperty [value: 24]
IntegerProperty [value: 36]
IntegerProperty [value: 18]
--------------
IntegerProperty [value: 12]
IntegerProperty [value: 8]
IntegerProperty [value: 36]
IntegerProperty [value: 18]
Run Code Online (Sandbox Code Playgroud)

我们可以看到模型正确更新但不是视图,为什么?


工作实例

(接受了James_D的非常简单但很好的答案:)

这是一个包含属性记录的完整示例,用于说明解决方案:

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 );
   }
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

正如所料

Jam*_*s_D 6

SortedList观察它的底层ObservableList.因此,只有在基础列表触发更改事件时,它才会更新其顺序.

对于一个可观察列表,当其中一个元素的状态发生变化时触发更新事件(与列表添加,删除或重新排序元素相反),它必须遵守相应的属性.除非您使用提取器告诉它这样做,否则不会发生这种情况.提取器是一个函数,它将列表中的元素映射到应该观察的属性数组:如果这些属性发生更改,列表将触发更新事件.在您的方案中,列表是排序列表的基础列表,这将允许排序列表重新排序.

因此,您需要创建基础列表

final ObservableList<IntegerProperty> il =
   FXCollections.observableArrayList(
      ( IntegerProperty intProp ) -> new Observable[]{ intProp });
Run Code Online (Sandbox Code Playgroud)

(即,您要观察的属性是元素本身).