2 Replies Latest reply on Apr 30, 2013 8:48 PM by shakir.gusaroff

    TextField bidirectional data binding to non-String values

    JGagnon
      It looks like this question has been asked many times already, but I haven't found a suitable answer that helps me.

      I'm trying to figure out how to bind bi-directionally a non-String value in my data model to a TextField control on a UI screen. Binding a String value to the field doesn't seem to be a big deal, but if you need to bind something other than a String, it becomes a problem. Compounding the problem, right now I think I'm getting lost in the sea of Property and ObservableValue class hierarchies and which is appropriate for which purposes. The JavaFX 2.2 API seems to indicate the use of a StringConverter instance, but I'm still not getting it right, because I still get a compile error indicating:

      The method bindBidirectional(Property<?>, Format) in the type StringProperty is not applicable for the arguments (IntegerProperty, StringConverter<Integer>). What am I missing? I found one entry in this forum that seemed to hint that doing what I'm proposing above is rather involved and not trivial. Is this still the case or has a "simple" solution been made available?

      Thanks,
      Joe
        • 1. Re: TextField bidirectional data binding to non-String values
          James_D
          The problem is that IntegerProperty implements Property<Number>, not Property<Integer> (somewhat counter-intuitively).

          So you need to provide a StringConverter<Number>. For example:
          import javafx.application.Application;
          import javafx.beans.property.IntegerProperty;
          import javafx.beans.property.SimpleIntegerProperty;
          import javafx.event.ActionEvent;
          import javafx.event.EventHandler;
          import javafx.geometry.Insets;
          import javafx.scene.Scene;
          import javafx.scene.control.Button;
          import javafx.scene.control.TextField;
          import javafx.scene.layout.HBox;
          import javafx.stage.Stage;
          import javafx.util.StringConverter;
          
          public class TextFieldBindingTest extends Application {
          
            @Override
            public void start(Stage primaryStage) {
              final IntegerProperty count = new SimpleIntegerProperty(0);
              final TextField tf = new TextField();
              final Button increment = new Button("Increment");
              final Button decrement = new Button("Decrement");
              increment.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                  count.set(count.get() + 1);
                }
              });
              decrement.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                  count.set(count.get() - 1);
                }
              });
              tf.textProperty().bindBidirectional(count, new StringConverter<Number>() {
          
                @Override
                public Number fromString(String text) {
                  return Integer.valueOf(text);
                }
          
                @Override
                public String toString(Number number) {
                  return number.toString();
                }
          
              });
          
              HBox root = new HBox(5);
              root.getChildren().addAll(tf, increment, decrement);
              root.setPadding(new Insets(10));
              primaryStage.setScene(new Scene(root));
              primaryStage.show();
            }
          
            public static void main(String[] args) {
              launch(args);
            }
          }
          Edited by: James_D on Apr 30, 2013 1:39 PM
          1 person found this helpful
          • 2. Re: TextField bidirectional data binding to non-String values
            shakir.gusaroff
            You can replace
            tf.textProperty().bindBidirectional(count, new StringConverter<Number>() {
             
                  @Override
                  public Number fromString(String text) {
                    return Integer.valueOf(text);
                  }
             
                  @Override
                  public String toString(Number number) {
                    return number.toString();
                  }
             
                });
             
            with
                
                tf.textProperty().bindBidirectional(count ,new NumberStringConverter ()  );
             
            1 person found this helpful