一、概述
Spinner是一个单行文本域,允许用户从一个有序序列中选择一个数字或者对象。Spinner通常提供一对小箭头按钮来逐步遍历序列中的元素。键盘的上/下箭头键也可以循环遍历这些元素。它也允许用户在Spinner中直接输入一个(有效的)值。尽管Combo Box提供了类似的功能,但是Spinner有些场景会更加适合。因为它不需要一个可隐藏重要数据的下拉列表。还有,它拥有循环和无穷数据模型等特性。其无穷数据模型是通过SpinnerValueFactory实现的,这和其他JavaFX UI控件使用的ObservableList数据模型不一样。
Spinner的序列数据是使用SpinnerValueFactory来定义的。可以通过Spinner类的构造函数传入此对象来进行设置。JavaFX中提供了一些常用类型的SpinnerValueFactory,如下:
- SpinnerValueFactory.IntegerSpinnerValueFactory
- SpinnerValueFactory.DoubleSpinnerValueFactory
- SpinnerValueFactory.ListSpinnerValueFactory
Spinner包含一个TextField子组件,用于展示或者修改当前值,被称作编辑器。默认情况下,Spinner是不可编辑的,但你可以通过设置其editable属性为true来开启它。编辑器会通过监听Value Factory的value属性变化来保持数据同步。如果用户在编辑器中修改了值,这很可能导致Spinner本身的值和编辑器的值不一致。此时用户必须通过敲击Enter键来提交编辑的内容,以确保二者的值保持一致。
该控件始于JavaFX 8u
40。
二、自有属性
- BooleanProperty editable
- ReadOnlyObjectProperty<TextField> editor
Spinner的编辑器
- ObjectProperty<SpinnerValueFactory<T>> valueFactory
Value Factory是Spinner控件的数据模型,没有它Spinner就不可用
- ReadOnlyObjectProperty<T> value
一个只读属性,它和Value Factory的Value属性绑定
三、箭头按钮样式常量
- String STYLE_CLASS_ARROWS_ON_LEFT_HORIZONTAL
指示箭头按钮被水平放置在Spinner左边
- String STYLE_CLASS_ARROWS_ON_LEFT_VERTICAL
指示箭头按钮被垂直放置在Spinner左边
- String STYLE_CLASS_ARROWS_ON_RIGHT_HORIZONTAL
指示箭头按钮被水平放置在Spinner右边
- String STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL
指示后退按钮放在Spinner的左边,前进按钮放在Spinner的右边
- String STYLE_CLASS_SPLIT_ARROWS_VERTICAL
指示箭头按钮被放置在Spinner的上面和下面,宽度会自适应拉伸
- 是不是好像没有垂直放在右边的选项? 别慌,因为默认就是垂直放在右边。
四、构造函数
- Spinner()
默认构造函数,使用默认的'spinner'样式类,编辑器不可编辑
- Spinner(double min, double max, double initialValue)
Value Factory会被设置为SpinnerValueFactory.DoubleSpinnerValueFactory,设置最小值、最大值和初始值,默认步进量为1
- Spinner(double min, double max, double initialValue, double amountToStepBy)
Value Factory会被设置为SpinnerValueFactory.DoubleSpinnerValueFactory,设置最小值、最大值、初始值和步进量。
- Spinner(int min, int max, int initialValue)
Value Factory会被设置为SpinnerValueFactory.IntegerSpinnerValueFactory,设置最小值、最大值和初始值,默认步进量为1
- Spinner(int min, int max, int initialValue, int amountToStepBy)
Value Factory会被设置为SpinnerValueFactory.IntegerSpinnerValueFactory,设置最小值、最大值、初始值和步进量。
- Spinner(ObservableList<T> items)
Value Factory会被设置为SpinnerValueFactory.ListSpinnerValueFactory.
- Spinner(SpinnerValueFactory<T> valueFactory)
使用指定的Value Factory
五、自有方法
- void decrement()
试图后退一步,底层会调用SpinnerValueFactory.decrement(1)
- void decrement(int steps)
试图退后指定步数,底层会调用SpinnerValueFactory.decrement(steps)
- void increment()
试图前进一步,底层会调用SpinnerValueFactory.increment(1)
- void increment(int steps)
试图前进指定步数,底层会调用SpinnerValueFactory.increment(steps)
- boolean isEditable()
返回编辑器是否可编辑
- void setEditable(boolean value)
设置编辑器是否可编辑
- SpinnerValueFactory<T> getValueFactory()
获取Value Factory
- void setValueFactory(SpinnerValueFactory<T> value)
设置Value FactorySets the value of the property valueFactory.
- TextField getEditor()
获取编辑器
- T getValue()
获取Spinner的值
六、示例代码
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Spinner; import javafx.scene.control.SpinnerValueFactory; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.Arrays; public class SpinnerApp extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) throws Exception { primaryStage.setScene(new Scene(createContent())); primaryStage.show(); } public Parent createContent() { HBox intBlock = new HBox(30); HBox stringBlock = new HBox(30); HBox doubleBlock = new HBox(30); String[] styles = { "spinner", //默认箭头按钮是垂直居右 Spinner.STYLE_CLASS_ARROWS_ON_RIGHT_HORIZONTAL, Spinner.STYLE_CLASS_ARROWS_ON_LEFT_VERTICAL, Spinner.STYLE_CLASS_ARROWS_ON_LEFT_HORIZONTAL, Spinner.STYLE_CLASS_SPLIT_ARROWS_VERTICAL, Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL }; Spinner[] intSpinners = new Spinner[styles.length]; Spinner[] stringSpinners = new Spinner[styles.length]; Spinner[] doubleSpinners = new Spinner[styles.length]; for (int i = 0; i < styles.length; i++) { //Integer Spinner SpinnerValueFactory svf = new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 99); Spinner sp = new Spinner(); sp.setValueFactory(svf);//设置Value Factory sp.getStyleClass().add(styles[i]);//设置箭头按钮的位置样式 sp.setPrefWidth(80); sp.setEditable(true);//设置可编辑 intSpinners[i] = sp; //Double Spinner svf = new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 10.0, 0.5, 0.01); sp = new Spinner(); sp.setValueFactory(svf); sp.getStyleClass().add(styles[i]); sp.setPrefWidth(90); doubleSpinners[i] = sp; //String Spinner ObservableList<String> items = FXCollections.observableArrayList("Grace", "Matt", "Katie"); svf = new SpinnerValueFactory.ListSpinnerValueFactory<>(items); sp = new Spinner(); sp.setValueFactory(svf); sp.setPrefWidth(100); sp.getStyleClass().add(styles[i]); if (i % 2 == 0) { sp.getValueFactory().setWrapAround(true);//循环切换:当前进到最后一个值时,再点前进是就显示第一个值 } stringSpinners[i] = sp; } intBlock.getChildren().addAll(Arrays.asList(intSpinners)); doubleBlock.getChildren().addAll(Arrays.asList(doubleSpinners)); stringBlock.getChildren().addAll(Arrays.asList(stringSpinners)); //<editor-fold defaultstate="collapsed" desc="自定义Value Facroty,显示2的X次方,对X进行步进"> SpinnerValueFactory svf = new SpinnerValueFactory<Double>() { int power = 0; @Override public void decrement(int steps) { power--; updateValue(); } @Override public void increment(int steps) { power++; updateValue(); } public void updateValue() { setValue(Math.pow(2, power)); } }; svf.setValue(1); Spinner sp = new Spinner(svf); sp.setPrefWidth(100); //</editor-fold> return new VBox(25, intBlock, doubleBlock, stringBlock, sp); } }