Bind the result of list.contains() method

1.2k views Asked by At

I want to bind text field to indicate whether list of integer contain 1. i have a button that insert 1 to the list and I want the text field will update but this doesn't happens. why and how can i repair it?

@Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("Hello World!");
    final List<Integer> list = new ArrayList<Integer>();
    Button btn = new Button();
    btn.setText("Say 'Hello World'");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            list.add(1);
        }
    });
    TextField txt = new TextField();
    txt.textProperty().bind(new SimpleStringProperty(String.valueOf(list.contains(1))));
    VBox root = new VBox();
    root.getChildren().addAll(btn,txt);
    primaryStage.setScene(new Scene(root, 300, 250));
    primaryStage.show();
}
1

There are 1 answers

4
Uluk Biy On

Try creating a BooleanBinding:

@Override
public void start( final Stage primaryStage )
{

    primaryStage.setTitle( "Hello World!" );
    final List<Integer> list = new ArrayList<>();

    // we need an ObservableList, duh, to observe!
    final ObservableList<Integer> oblist = FXCollections.observableArrayList( list );
    Button btn = new Button();
    btn.setText( "Say 'Hello World'" );
    btn.setOnAction( new EventHandler<ActionEvent>()
    {
        @Override
        public void handle( ActionEvent event )
        {
            oblist.add( 1 );
        }
    } );
    BooleanBinding bb = Bindings.createBooleanBinding( () -> oblist.contains( 1 ), oblist );

    TextField txt = new TextField();
    txt.textProperty().bind( bb.asString() );
    VBox root = new VBox();
    root.getChildren().addAll( btn, txt );

    final Scene scene = new Scene( root, 400, 300 );
    primaryStage.setScene( scene );
    primaryStage.show();
}

I still doesn't understand what problem with my code, can you explain me please?

Let's break down the code: new SimpleStringProperty(String.valueOf(list.contains(1)));

-> initially list.contains(1) = false
-> String.valueOf(false) = "false"
-> new SimpleStringProperty("false") will create new instance of StringProperty with initial value "false", and this instance is bound to textProperty of textField. That is it, since we are initiating with the String value "false", no further observation for list and its content where it contains 1 or not. Hence we need an observable list here.

Thus the textfield's text will change in sync if the bound StringProperty is changed. Rewriting as,

StringProperty sp = new SimpleStringProperty(String.valueOf(list.contains(1)));
txt.textProperty().bind(sp);
sp.set("newVal"); // at this point textfield's text will be updated with 
// "newVal", but it has nothing about list and its content.