Creating an Integer Spinner in JavaFX

I came across an issue while building a Spinner in a JavaFX application. While I was able to insert the UI element in place, it wasn’t getting properly initialized with a SpinnerValueFactory, leading to an inability to set a value for the element (since you have to set the value on the factory, not on the Spinner itself). Since I was mainly building this using fxml, I was looking for a solution preferably not in code. (note: this was purely for consistency; I don’t shy away from writing Java, but I’d rather implement the UI properties in one place).

In my searching, I found this solution on StackOverflow, setting the SpinnerValueFactory as a child element of the Spinner:

<Spinner fx:id="mySpinner">
<valueFactory>
<SpinnerValueFactory.IntegerSpinnerValueFactory min="0" max="10"/>
</valueFactory>
</Spinner>

When I tried this, I ended up with some errors:

javafx.fxml.LoadException: SpinnerValueFactory.IntegerSpinnerValueFactory is not a valid type.

I continued getting this exception even after I ensured I was importing the right classes, paths, etc. Since I didn’t much care for the other answer on the SO page (defining and using variables in the fxml itself), I decided to address this more in code.

Now, if you’ve worked with JavaFX at all, you know you can use the @FXML annotation to inject the various nodes in the fxml document, based on the fx:id property; this means you don’t have to manually build the element and insert it into the document flow. The downside is that you don’t get the opportunity to pass things at time of construction, such as the information we need to instantiate the Factory.

However, we do have a tool at our disposal: the initialize() method. According to the docs, this method is called after construction and injection of all the fxml elements so we can access them before we start in with the real logic of the application.

First, let’s set up our (extremely sparse, illustrative purposes only) FXML so we have a starting point:

<HBox ...>
<Spinner fx:id="mySpinner" />
</HBox>

There are two different ways we can get the initialization functionality working. First, the “long” way:

public class MyForm implements Initializable() {
public MyForm() {}
    @Override 
public void initialize(URL location, Resources resources) {
initSpinner();
}
}

Now, since I’ve never used either the location or resources arguments, I prefer using the abbreviated version:

public class MyForm {
public MyForm() {}
    @FXML
public void initialize() {
initSpinner();
}
}

In either case, we’ll be doing all the spinner initialization in the initSpinner method:

import javafx.scene.control.*
public class MyForm {
@FXML
Spinner mySpinner;
    private void initSpinner() {
mySpinner.setValueFactory(
new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 10);
);
}
}

And now, after we have instantiated the SpinnerValueFactory, we’ll be able to use it, set the value, etc. A crude example of this:

public class MyForm {
... all that stuff from above
    public void updateSpinnerValue(Integer newValue) {
mySpinner.getValueFactory().setValue(newValue);
}
}

Cheers!