2

I am trying to bind the value of a Spinner to an integer property. This answer is not satisfactory, because I do not want to create a new IntegerProperty, but instead bind the spinner's value to an existing one.

I tried to create a new IntegerProperty as shown in that answer, and then bind it to the existing one. However, this example code does not work:

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane pane = new StackPane();

        IntegerProperty controlled = new SimpleIntegerProperty(); // I don't want to change this.

        final Spinner<Integer> spinner = new Spinner<>(0, 10, 5, 1);

        ObjectProperty<Integer> bridgeObject = new SimpleObjectProperty<>();
        IntegerProperty bridgeInteger = IntegerProperty.integerProperty(bridgeObject); // "Returns a IntegerProperty that wraps a Property and is bidirectionally bound to it."

        SpinnerValueFactory<Integer> valueFactory = spinner.getValueFactory(); // not null
        ObjectProperty<Integer> integerObjectProperty = valueFactory.valueProperty(); // not null
        integerObjectProperty.bindBidirectional(bridgeObject); // Throws NullPointerException, but not while debugging?!

        bridgeInteger.bindBidirectional(controlled);

        pane.getChildren().add(spinner);

        primaryStage.setScene(new Scene(pane, 300, 275));
        primaryStage.show();
    }
}

Questions:

  1. Is there a better way to bind to an existing IntegerProperty than to create two intermediate "bridge" Properties?
  2. If not, why does my example code throw a NullPointerException? I checked with assertions that integerObjectProperty is not null. Oddly, the exception is not thrown if the code is debugged line by line (Why?). The author of the other question claimed he had done something like this successfully, but didn't respond to another user's request to post the code.
Reinis Mazeiks
  • 1,168
  • 1
  • 10
  • 21

1 Answers1

3

Your null pointer exception is probably due to bridgeObject.get() being null when you do the binding.

All you need is

@Override
public void start(Stage primaryStage) throws Exception {
    StackPane pane = new StackPane();

    IntegerProperty controlled = new SimpleIntegerProperty(); // I don't want to change this.

    final Spinner<Integer> spinner = new Spinner<>(0, 10, 5, 1);

    spinner.getValueFactory().valueProperty().bindBidirectional(controlled.asObject());

    pane.getChildren().add(spinner);

    primaryStage.setScene(new Scene(pane, 300, 275));
    primaryStage.show();
}
James_D
  • 201,275
  • 16
  • 291
  • 322