How to create an Integer counter with FXML

I am trying to create an Integer Spinner , but a Double is being created instead.

Test.class

 package com.neonorb.test; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.geometry.Insets; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; public class Test extends Application{ @Override public void start(Stage stage) throws Exception { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Demo.fxml")); Parent root = fxmlLoader.load(); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } 

DemoController.class

 package com.neonorb.test; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Spinner; import java.net.URL; import java.util.ResourceBundle; public class DemoController implements Initializable{ @FXML private Spinner<Integer> spinner; @Override public void initialize(URL url, ResourceBundle resourceBundle) { System.out.println(spinner.getValue()); } } 

Demo.fxml

 <?import javafx.scene.layout.BorderPane?> <?import javafx.scene.control.Spinner?> <?import java.lang.Integer?> <BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="com.neonorb.test.DemoController"> <Spinner fx:id="spinner" min="1" initialValue="1" amountToStepBy="1"> <max> <Integer fx:constant="MAX_VALUE"/> </max> </Spinner> </BorderPane> 

When I execute it, it outputs 1.0 , which, as I know, creates a Double spinner.

I guess what happens is that FXMLLoader chooses the wrong constructor for Spinner . How to choose an Integer one?

+5
source share
2 answers

Problem

You need to set the factory value to the counter. Otherwise, you will encounter a type of coercion. If you cannot set it there, you can define Integer values โ€‹โ€‹that call the static value Of ().

JavaFX Introduction to FXML notes on type of enforcement :

Type of coercion

FXML uses "type coercion" to convert property values โ€‹โ€‹to the appropriate type as needed. The type of coercion is required because the only data types supported by XML are elements, text, and attributes (whose values โ€‹โ€‹are also textual). However, Java does support several different data types, including built-in primitive value types as well as extensible reference types.

The FXML loader uses the coerce () method of the BeanAdapter to perform any type conversion required. This method is capable of performing basic primitive type conversions, such as String for boolean or int double, and also converts String to class or String to Enum. Additional conversions can be implemented by defining the static valueOf () method on the target type.

<h / ">

Factory Solution

An IntegerSpinnerValueFactory already exists. Since this is a nested SpinnerValueFactory class, you should use it with a dot in the tag name.

Three constructors are available, you can set min / max and min / max / initialValue and min / max / initialValue / amountToStepBy. This is done by setting as an attribute.

Demo.fxml

 <?import java.lang.*?> <?import java.util.*?> <?import javafx.util.* ?> <?import javafx.scene.*?> <?import javafx.scene.control.* ?> <?import javafx.scene.layout.* ?> <BorderPane xmlns:fx="http://javafx.com/fxml/1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="demoapp.DemoController"> <center> <Spinner fx:id="spinner" BorderPane.alignment="CENTER" > <valueFactory> <SpinnerValueFactory.IntegerSpinnerValueFactory min="0" max="10"/> </valueFactory> </Spinner> </center> </BorderPane> 

<h / ">

Solution without Factory

You can also define two variables and use them as static valueOf (). As described in the above quote with the static value of the Of () method. Thus, your FXMLLoader should not guess which type you probably have in mind. It calls the constructor with int values.

Demo.fxml

 <?import java.lang.*?> <?import java.util.*?> <?import javafx.util.* ?> <?import javafx.scene.*?> <?import javafx.scene.control.* ?> <?import javafx.scene.layout.* ?> <BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="demoapp.DemoController" xmlns="http://javafx.com/javafx/8.0_40" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" > <center> <fx:define> <Integer fx:id="min" fx:value="0"/> <Integer fx:id="max" fx:value="10"/> </fx:define> <Spinner fx:id="spinner" BorderPane.alignment="CENTER" min="$min" max="$max"> </Spinner> </center> </BorderPane> 
+9
source

A small update for the FXML file ...

Enable

 <?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory?> 

then

  <Spinner fx:id="spinner" BorderPane.alignment="CENTER" editable="true" > <valueFactory> <SpinnerValueFactory.IntegerSpinnerValueFactory min="0" max="10" initialValue="5" amountToStepBy="1"/> </valueFactory> </Spinner> 
+1
source

All Articles