如何使用 FXML 创建整数微调器
How to create an Integer spinner with FXML
我正在尝试创建一个 Integer
Spinner
,但是却创建了一个 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
一个?
问题
您需要为微调器设置一个值工厂。否则你将面临类型强制。如果你不能在那里设置它,你可以定义将由静态 valueOf() 调用的整数值。
JavaFX Introduction to FXML 关于Type Coercion的注释:
Type Coercion
FXML uses "type coercion" to convert property values to the
appropriate type as needed. Type coercion is required because the only
data types supported by XML are elements, text, and attributes (whose
values are also text). However, Java supports a number of different
data types including built-in primitive value types as well as
extensible reference types.
The FXML loader uses the coerce() method of BeanAdapter to perform any
required type conversions. This method is capable of performing basic
primitive type conversions such as String to boolean or int to double,
and will also convert String to Class or String to Enum. Additional
conversions can be implemented by defining a static valueOf() method
on the target type.
工厂解决方案
已经存在 IntegerSpinnerValueFactory. Because it is a nested class of 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>
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>
我正在尝试创建一个 Integer
Spinner
,但是却创建了一个 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
一个?
问题
您需要为微调器设置一个值工厂。否则你将面临类型强制。如果你不能在那里设置它,你可以定义将由静态 valueOf() 调用的整数值。
JavaFX Introduction to FXML 关于Type Coercion的注释:
Type Coercion
FXML uses "type coercion" to convert property values to the appropriate type as needed. Type coercion is required because the only data types supported by XML are elements, text, and attributes (whose values are also text). However, Java supports a number of different data types including built-in primitive value types as well as extensible reference types.
The FXML loader uses the coerce() method of BeanAdapter to perform any required type conversions. This method is capable of performing basic primitive type conversions such as String to boolean or int to double, and will also convert String to Class or String to Enum. Additional conversions can be implemented by defining a static valueOf() method on the target type.
工厂解决方案
已经存在 IntegerSpinnerValueFactory. Because it is a nested class of 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>
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>