有人可以帮我在 JavaFX 中制作一个倒计时器吗?我需要从标签中获取时间(时间由滑块设置),并且我想查看每秒剩余的分钟和秒数。当按下按钮时应该开始倒计时。我搜索了 Stack Overflow,并尝试使用 ChatGPT 来完成此操作,但仍然遇到问题。这是 ChatGPT 给我的代码,但它不起作用。它说时间线未初始化。
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class CountdownTimer extends Application {
private int hours;
private int minutes;
private int seconds;
private Label timerLabel = new Label();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
TextField hoursField = new TextField();
hoursField.setPromptText("Hours");
TextField minutesField = new TextField();
minutesField.setPromptText("Minutes");
TextField secondsField = new TextField();
secondsField.setPromptText("Seconds");
Button startButton = new Button("Start Timer");
startButton.setOnAction(event -> {
// Parse user input for hours, minutes, and seconds
hours = Integer.parseInt(hoursField.getText());
minutes = Integer.parseInt(minutesField.getText());
seconds = Integer.parseInt(secondsField.getText());
// Start the countdown timer
startCountdown();
});
root.getChildren().addAll(hoursField, minutesField, secondsField, startButton, timerLabel);
Scene scene = new Scene(root, 300, 200);
primaryStage.setTitle("Countdown Timer");
primaryStage.setScene(scene);
primaryStage.show();
}
private void startCountdown() {
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
// Decrease one second
if (seconds > 0) {
seconds--;
} else {
// If seconds reach zero, decrement minutes and set seconds to 59
if (minutes > 0) {
minutes--;
seconds = 59;
} else {
// If minutes reach zero, decrement hours and set minutes and seconds to 59
if (hours > 0) {
hours--;
minutes = 59;
seconds = 59;
} else {
// If hours, minutes, and seconds reach zero, stop the timer
hours = 0;
minutes = 0;
seconds = 0;
timeline.stop();
}
}
}
// Update the label with the new values
timerLabel.setText(String.format("Time Left: %02d:%02d:%02d", hours, minutes, seconds));
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
消息“时间线可能未初始化”意味着您正在尝试在构建之前使用
timeline
。您在传递给时间轴构造函数的事件处理程序中调用 timeline.stop()
;由于构造函数尚未完成,编译器无法保证在事件处理程序运行时实际已为 timeline
分配了值。换句话说,timeline
可能会被初始化。
解决此问题的一种方法是单独添加关键帧。这样,Timeline 构造函数就完全完成了:
Timeline timeline = new Timeline();
// Construction complete; now timeline can be used in an event handler.
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(1), event -> {
// Decrease one second
if (seconds > 0) {
seconds--;
} else {
// If seconds reach zero, decrement minutes and set seconds to 59
if (minutes > 0) {
minutes--;
seconds = 59;
} else {
// If minutes reach zero, decrement hours and set minutes and seconds to 59
if (hours > 0) {
hours--;
minutes = 59;
seconds = 59;
} else {
// If hours, minutes, and seconds reach zero, stop the timer
hours = 0;
minutes = 0;
seconds = 0;
timeline.stop();
}
}
}
// Update the label with the new values
timerLabel.setText(String.format("Time Left: %02d:%02d:%02d", hours, minutes, seconds));
}));
另一种方法是将
timeline
声明为私有字段,而不是局部变量。这是有效的,因为一旦封闭类完成了它自己的构造函数,每个字段都保证被初始化。 (如果您的代码从未为某个字段分配过值,则该字段将自动初始化为 null。)