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

JavaFX SortedList:侦听列表更改和列表项更新事件,java,sorting,javafx-8,Java,Sorting,Javafx 8,用例: 有序列表视图(或表视图) 显示后进行插入 显示后会对按键进行更新 启动时的列表: 添加18后: 更新后: 因为你看不到任何变化 守则: public final class SortedListTest extends Application { @Override public void start( Stage stage ) throws Exception { final ObservableList<IntegerProperty>

用例:

  • 有序列表视图(或表视图)
  • 显示后进行插入
  • 显示后会对按键进行更新
启动时的列表:

添加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 );
   }
}
我们可以看到模型已正确更新,但视图未正确更新,为什么?


工作示例 (在接受了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 );
   }
}
公共最终类SortedListTest扩展应用程序{
课堂记录{
final IntegerProperty_key=new SimpleIntegerProperty();
final StringProperty_值=新的SimpleStringProperty();
记录(整数k,字符串v){
_密钥集(k);
_设定值(v);
}
@凌驾
公共字符串toString(){
返回“Key=“+”Key.get()+”,value=“+”value.get();
}
}
@凌驾
public void start(Stage)引发异常{
最终观察者=
FXCollections.observableArrayList(
rec->新的可观测[]{rec._key});
增加(新记录(12个“Douze”);
增加(新记录(24,“文之四”);
增加(新记录(36,“特伦特六号”);
最终按钮添加=新按钮(“添加18”);
最终按钮更新=新按钮(“更新24到8”);
最终HBox ctrl=新HBox(4.0,添加,更新);
最终分拣清单分拣清单=
已排序((l,r)->Integer.compare(l._key.get(),r._key.get());
最终ListView listVw=新ListView(sortedList);
舞台场景(新场景)(
新的边框窗格(listVw,ctrl,null,null,null),200140);
stage.show();
添加.设置操作(e->{
增加(新记录(18,“Dix huit”);
System.err.println(“--------------”;
il.stream().forEach(System.err::println);
});
更新设置动作(e->{
il.get(1)和U键set(8);
System.err.println(“--------------”;
il.stream().forEach(System.err::println);
});
}
公共静态void main(字符串[]args){
发射(args);
}
}
结果是:


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

要使可观察列表在其一个元素的状态更改时触发更新事件(与添加、删除或重新排序元素的列表相反),它必须观察相应的属性。除非你让它这样做,否则这不会发生。提取器是一个函数,它将列表中的元素映射到应该观察的属性数组:如果这些属性发生更改,列表将触发更新事件。在您的场景中,列表是已排序列表的基础列表,这将允许已排序列表对自身进行重新排序

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

final ObservableList<IntegerProperty> il =
   FXCollections.observableArrayList(
      ( IntegerProperty intProp ) -> new Observable[]{ intProp });
最终可观察列表il=
FXCollections.observableArrayList(
(IntegerProperty intProp)->新的可观测[]{intProp});

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

能否为intProp添加代码?我看不出它是什么。它只是lambda(即list元素)的参数@James_D如果列表不包含可观察的属性,是否有提取器的替代方案?只是一个与您的问题无关的注意事项:您应该使用
(l,r)->Integer.compare(l._key.get(),r._key.get())
作为比较器。(如果减法运算导致溢出,您的比较器将发生不好的事情。)l和r是整数,溢出是如何发生的?例如,如果
l.\u key.get()==Integer.MAX\u VALUE
(=2147483647)和
r.\u key.get()=-1
,则
l.\u key.get()-r.\u key.get()
将给出错误的结果(事实上是由于错误的标志)是的,当然!我已经报告了你的建议。
final ObservableList<IntegerProperty> il =
   FXCollections.observableArrayList(
      ( IntegerProperty intProp ) -> new Observable[]{ intProp });