it-swarm.com.ru

Как создать Integer Spner с FXML

Я пытаюсь создать IntegerSpinner, но вместо этого создается Double.

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>

Когда я выполняю его, он выводит 1.0, что, как я знаю, делает Double спиннер.

Я предполагаю, что происходит то, что FXMLLoader выбирает неправильный конструктор для Spinner. Как выбрать Integer?

7
Chris Smith

Проблема

Вам нужно установить заводское значение для счетчика. В противном случае вы столкнетесь с принуждением типов. Если вы не можете установить его там, вы можете определить целочисленные значения, которые будут вызываться статическим значением valueOf ().

JavaFX Введение в FXML отмечает о приведение типов :

Тип принуждения

FXML использует "приведение типов" для преобразования значений свойств в соответствующий тип по мере необходимости. Приведение типов требуется, потому что единственными типами данных, поддерживаемыми XML, являются элементы, текст и атрибуты (значения которых также являются текстовыми). Однако Java поддерживает ряд различных типов данных, включая встроенные типы примитивных значений, а также расширяемые ссылочные типы.

Загрузчик FXML использует метод coerce () BeanAdapter для выполнения любых необходимых преобразований типов. Этот метод способен выполнять базовые примитивные преобразования типов, такие как String в boolean или int в double, а также преобразует String в Class или String в Enum. Дополнительные преобразования могут быть реализованы путем определения статического метода valueOf () для целевого типа.


Решение с завода

Уже существует IntegerSpinnerValueFactory . Поскольку это вложенный класс SpinnerValueFactory , вы должны использовать его с точкой в ​​имени тега.

Доступно три конструктора, вы можете установить min/max и min/max/initialValue и min/max/initialValue/amountToStepBy. Это делается путем установки его в качестве атрибута.

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>

Решение без фабрики

Вы также сможете определить две переменные и использовать их в качестве статического valueOf (). Как описано в приведенной выше цитате со статическим методом valueOf (). Так что вашему FXMLLoader не нужно угадывать, какой тип вы имеете в виду. Он вызывает конструктор со значениями int.

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>
12
NwDev

Небольшое обновление для файла FXML ...

Включают

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

затем

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