如何在微调器中设置 3 个值
How can I set 3 values in spinner
我希望在一个微调器中显示 02:25:12AM 小时、分钟、秒的时间。我怎样才能做到这一点?我只为一个值做了
<Spinner fx:id="spinner" layoutX="350.0" layoutY="10.0" initialValue="60"
max="120" prefHeight="25.0" prefWidth="60.0" />
它显示类似
的错误
jaavaFx.scene.control.Spinner does not support min/max/intial propery
但效果很好。现在我想为 3 个值做这件事。
正如@UlukBiy 在评论中所说,您可能想在这里使用三个微调器。您可能还想实现 "wrap around",这样如果您将秒数增加到超过 59,它会重置为 0 并且分钟会增加,等等。
此外,要设置最小值和最大值,请将它们设置在 SpinnerValueFactory
上,而不是 Spinner
本身。请参阅 Spinner
, SpinnerValueFactory
, and SpinnerValueFactory.IntegerSpinnerValueFactory
.
的 Javadocs
这是一个完整的示例(FXML 格式):
TimeSpinner.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory ?>
<HBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="TimeSpinnerController">
<Spinner fx:id="hourSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="hourValueFactory">
<min>0</min>
<max>23</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>
</valueFactory>
</Spinner>
<Spinner fx:id="minuteSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="minuteValueFactory">
<min>0</min>
<max>59</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>>
</valueFactory>
</Spinner>
<Spinner fx:id="secondSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="secondValueFactory">
<min>0</min>
<max>59</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>>
</valueFactory>
</Spinner>
</HBox>
TimeSpinnerController:
import java.time.Duration;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.Spinner;
public class TimeSpinnerController {
@FXML
private Spinner<Integer> hourSpinner ;
@FXML
private Spinner<Integer> minuteSpinner ;
@FXML
private Spinner<Integer> secondSpinner ;
private ReadOnlyObjectWrapper<Duration> time = new ReadOnlyObjectWrapper<>();
public void initialize() {
minuteSpinner.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue.intValue() == 59 && newValue.intValue() == 0) {
hourSpinner.increment();
}
if (oldValue.intValue() == 0 && newValue.intValue() == 59) {
hourSpinner.decrement();
}
});
secondSpinner.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue.intValue() == 59 && newValue.intValue() == 0) {
minuteSpinner.increment();
}
if (oldValue.intValue() == 0 && newValue.intValue() == 59) {
minuteSpinner.decrement();
}
});
time.bind(Bindings.createObjectBinding(this::computeTime, hourSpinner.valueProperty(),
minuteSpinner.valueProperty(), secondSpinner.valueProperty()));
}
public ReadOnlyObjectProperty<Duration> timeProperty() {
return time.getReadOnlyProperty() ;
}
public Duration getTime() {
return timeProperty().get();
}
private Duration computeTime() {
int seconds = secondSpinner.getValue();
int minutes = minuteSpinner.getValue();
int hours = hourSpinner.getValue();
int totalSeconds = (hours * 60 + minutes) * 60 + seconds ;
return Duration.ofSeconds(totalSeconds);
}
}
测试代码:
import java.io.IOException;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TimeSpinnerTest extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("TimeSpinner.fxml"));
HBox timeSpinner = loader.load();
TimeSpinnerController timeController = loader.getController() ;
Label label = new Label();
label.textProperty().bind(Bindings.createStringBinding(() -> {
long s = timeController.getTime().getSeconds() ;
return String.format("%02d:%02d:%02d", s / 3600, (s / 60) % 60, s % 60);
}, timeController.timeProperty()));
VBox root = new VBox(10, timeSpinner, label);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(24));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我希望在一个微调器中显示 02:25:12AM 小时、分钟、秒的时间。我怎样才能做到这一点?我只为一个值做了
<Spinner fx:id="spinner" layoutX="350.0" layoutY="10.0" initialValue="60"
max="120" prefHeight="25.0" prefWidth="60.0" />
它显示类似
的错误jaavaFx.scene.control.Spinner does not support min/max/intial propery
但效果很好。现在我想为 3 个值做这件事。
正如@UlukBiy 在评论中所说,您可能想在这里使用三个微调器。您可能还想实现 "wrap around",这样如果您将秒数增加到超过 59,它会重置为 0 并且分钟会增加,等等。
此外,要设置最小值和最大值,请将它们设置在 SpinnerValueFactory
上,而不是 Spinner
本身。请参阅 Spinner
, SpinnerValueFactory
, and SpinnerValueFactory.IntegerSpinnerValueFactory
.
这是一个完整的示例(FXML 格式):
TimeSpinner.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory ?>
<HBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="TimeSpinnerController">
<Spinner fx:id="hourSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="hourValueFactory">
<min>0</min>
<max>23</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>
</valueFactory>
</Spinner>
<Spinner fx:id="minuteSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="minuteValueFactory">
<min>0</min>
<max>59</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>>
</valueFactory>
</Spinner>
<Spinner fx:id="secondSpinner" prefWidth="60">
<valueFactory>
<javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory fx:id="secondValueFactory">
<min>0</min>
<max>59</max>
<wrapAround>true</wrapAround>
</javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory>>
</valueFactory>
</Spinner>
</HBox>
TimeSpinnerController:
import java.time.Duration;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.Spinner;
public class TimeSpinnerController {
@FXML
private Spinner<Integer> hourSpinner ;
@FXML
private Spinner<Integer> minuteSpinner ;
@FXML
private Spinner<Integer> secondSpinner ;
private ReadOnlyObjectWrapper<Duration> time = new ReadOnlyObjectWrapper<>();
public void initialize() {
minuteSpinner.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue.intValue() == 59 && newValue.intValue() == 0) {
hourSpinner.increment();
}
if (oldValue.intValue() == 0 && newValue.intValue() == 59) {
hourSpinner.decrement();
}
});
secondSpinner.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue.intValue() == 59 && newValue.intValue() == 0) {
minuteSpinner.increment();
}
if (oldValue.intValue() == 0 && newValue.intValue() == 59) {
minuteSpinner.decrement();
}
});
time.bind(Bindings.createObjectBinding(this::computeTime, hourSpinner.valueProperty(),
minuteSpinner.valueProperty(), secondSpinner.valueProperty()));
}
public ReadOnlyObjectProperty<Duration> timeProperty() {
return time.getReadOnlyProperty() ;
}
public Duration getTime() {
return timeProperty().get();
}
private Duration computeTime() {
int seconds = secondSpinner.getValue();
int minutes = minuteSpinner.getValue();
int hours = hourSpinner.getValue();
int totalSeconds = (hours * 60 + minutes) * 60 + seconds ;
return Duration.ofSeconds(totalSeconds);
}
}
测试代码:
import java.io.IOException;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TimeSpinnerTest extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("TimeSpinner.fxml"));
HBox timeSpinner = loader.load();
TimeSpinnerController timeController = loader.getController() ;
Label label = new Label();
label.textProperty().bind(Bindings.createStringBinding(() -> {
long s = timeController.getTime().getSeconds() ;
return String.format("%02d:%02d:%02d", s / 3600, (s / 60) % 60, s % 60);
}, timeController.timeProperty()));
VBox root = new VBox(10, timeSpinner, label);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(24));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}