You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX如何在Timeline倒计时结束时无需按钮触发切换场景

问题原因分析
    1. 方法参数不匹配:你定义的startQuiz方法要求传入ActionEvent类型的参数,但Timeline的setOnFinished回调中调用startQuiz()时没有传任何参数,直接触发方法签名不匹配报错。
    1. 场景对象未初始化:startQuiz方法中你已经通过FXMLLoader加载了新界面的根节点,但调用stage.setScene(scene)时使用的scene是全局未初始化的空变量,会触发空指针异常。
    1. 事件来源不存在:Timeline完成的回调中没有可直接使用的界面事件对象,你原来通过event.getSource()拿控件的逻辑无法生效,拿不到Stage对象。
    1. 变量命名冲突:startQuiz方法内重新定义了局部root变量,覆盖了全局定义的root变量,属于不必要的冗余操作。
修正后的代码方案
public class countDownScreenController implements Initializable {
    // 注入FXML中定义的根节点,注意你的倒计时界面FXML根节点要设置fx:id="root"
    @FXML
    private Parent root;
    private Stage stage;
    private StringProperty timerText;
    private int timerTotal;
    private Timeline timeLine;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        runTimer();
    }

    public void runTimer(){
        timerTotal = 3;
        setTimerText(timerTotal);
        timeLine = new Timeline();
        timeLine.setCycleCount(timerTotal);
        timeLine.getKeyFrames().add(new KeyFrame(Duration.seconds(1), e -> {
            timerTotal--;
            setTimerText(timerTotal);
        }));
        // 先设置完成回调再播放,避免极端情况倒计时过快回调未生效
        timeLine.setOnFinished(e -> {
            try {
                startQuiz();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        timeLine.play();
    }

    // 去掉ActionEvent参数,改为无参通用方法
    public void startQuiz () throws IOException {
        Parent quizRoot = FXMLLoader.load(getClass().getResource("/fxml/quizScreenScreen.fxml"));
        // 直接从已注入的当前界面根节点拿Stage
        stage = (Stage) root.getScene().getWindow();
        // 用新加载的界面根节点创建Scene再设置给Stage
        Scene scene = new Scene(quizRoot);
        stage.setScene(scene);
        stage.show();
    }

    // 原有构造、getter、setter逻辑无需调整
    public countDownScreenController() {
        timerText = new SimpleStringProperty();
    }

    public String getTimerText() {
        return timerText.get();
    }

    public StringProperty timerTextProperty() {
        return timerText;
    }

    public void setTimerText(String timerText) {
        this.timerText.set(timerText);
    }

    public void setTimerText(int remainingSeconds) {
        int minutes = remainingSeconds / 60;
        int seconds = remainingSeconds % 60;
        setTimerText(String.format("%02d:%02d", minutes, seconds));
    }

    // 若需要保留按钮点击触发切换的功能,新增重载方法即可,无需重复写逻辑
    @FXML
    public void startQuiz(ActionEvent event) throws IOException {
        startQuiz();
    }
}
额外注意事项
  • 必须在倒计时界面的FXML文件根节点上添加属性fx:id="root",否则@FXML注入的root会为空,触发空指针异常。
  • 确认/fxml/quizScreenScreen.fxml路径正确,注意文件名是否存在拼写错误(当前命名重复写了一次Screen,可核对实际文件名)。

内容的提问来源于stack exchange,提问作者sillyPin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 18:54:03