Himaloy
Himaloy

Reputation: 23

How to bind TextField and ProgressBar in JavaFx

I'm trying to Use reactive bindings to bind the value of alcoholPercentageField to the progress property of alcoholBar. The progress bar will "full" when alcoholic content is set to 20 % and empty when the alcoholic content is 0

My Code-

    public void start(Stage stage) throws Exception {
    stage.setTitle("Mead calculator");

    // Creating the fields and components
    TextField waterAmountField = new TextField();

    TextField alcoholPercentageField = new TextField();

    TextField sugarAmountField = new TextField();
    Label meadTotalAmount = new Label();
    Label assessmentLabel = new Label("");
    //assessmentLabel.textProperty().bind(alcoholPercentageField.textProperty());

    //Conditional Binding Error 

    assessmentLabel.textProperty().bind(Bindings.when((alcoholPercentageField.textProperty().lessThan(5))).then("Smart").otherwise("Bad"));

    ProgressBar alcoholBar = new ProgressBar();

    //Error is here
    alcoholBar.progressProperty().bind(alcoholPercentageField.textProperty() * 5);

Rest of the Code: some visual things

GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(25, 25, 25, 25));
    var columnOneConstraints = new ColumnConstraints(150, 150, Double.MAX_VALUE);
    columnOneConstraints.setHalignment(HPos.RIGHT);
    var columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
    columnTwoConstrains.setHgrow(Priority.SOMETIMES);
    grid.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);
    alcoholBar.setMaxWidth(Double.MAX_VALUE);
    GridPane.setColumnSpan(alcoholBar, 2);
    GridPane.setHalignment(assessmentLabel, HPos.RIGHT);
    sugarAmountField.setDisable(true);

    grid.add(new Label("Water (l):"), 0, 0);
    grid.add(waterAmountField, 1, 0);
    
    grid.add(new Label("Vol-%:"), 0, 1);
    grid.add(alcoholPercentageField, 1, 1);

    grid.add(new Label("Sugar (kg):"),  0, 2);
    grid.add(sugarAmountField, 1, 2);

    grid.add(new Label("Lemons: "), 0, 3);
    grid.add(new Label("To taste"), 1, 3);

    grid.add(new Label("Mead total (kg):"), 0, 4);
    grid.add(meadTotalAmount, 1, 4);

    grid.add(alcoholBar, 0, 5);
    grid.add(assessmentLabel, 1, 6);
    // Okay, layout creation stops here
    
    
    // And of course set the scene and show the stage as always
    stage.setScene(new Scene(grid, 500, 400));
    stage.show();
}

}

Upvotes: 2

Views: 265

Answers (2)

Himu21
Himu21

Reputation: 88

You need to create some additional Property and Binding objects.

First, create properties for your TextField alcoholPercentageField. Then, you'll bind them using a StringConverter to convert the text entered into doubles.

Finally, use bindBidirectional to propagate and lastly bind it with progressBar by dividing 20 ( The progress bar will be "full" when alcoholic content is set to 20 %)

Code Will be like this-

    // Properties used for bindings
    DoubleProperty alcoholPercent = new SimpleDoubleProperty();

    //Setup the converters to get the input from the textfields
    StringConverter<? extends Number> converter = new DoubleStringConverter();
    
    Bindings.bindBidirectional(alcoholPercentageField.textProperty(), alcoholPercent, (StringConverter<Number>) converter);
    alcoholBar.progressProperty().bind(alcoholPercent.divide(20));

For Conditional Binding, check this Conditional Binding

Code would be like this-

    assessmentLabel.textProperty().bind(Bindings.when(alcoholPercent.lessThan(5)).then("Smart").otherwise("Bad"));
    assessmentLabel.textFillProperty().bind(Bindings.when(alcoholPercent.lessThan(5)).then(Color.GREEN).otherwise(Color.RED));

Upvotes: 1

James_D
James_D

Reputation: 209330

Use the Bindings API.

Note that the progress is supposed to be between 0 and 1, so if you are entering percentages, instead of proportions, into your text field you need to divide by 100:

alcoholBar.progressProperty().bind(Bindings.createDoubleBinding(
    () -> 0.05 * Double.parseDouble(alcoholPercentageField.getText()),
    alcoholPercentageField.textProperty()
));

You might want to implement more complex logic to, e.g. check for a valid number, or at least non-empty text field.

Upvotes: 1

Related Questions