【问题标题】:JavaFX, countdown timer in Label setTextJavaFX,标签setText中的倒数计时器
【发布时间】:2017-12-05 14:13:34
【问题描述】:

我正在构建用于进行测试的应用程序。我有一个在 SceneBuilder 中制作的场景。图像标签下有一个 ImageView,带有问题和 3 个按钮“A”、“B”、“C”,按钮的文本和问题的标签取自数据库,如果单击回答新图像,问题和答案正在加载,一切正常,但我想在角落里添加一个计时器。当屏幕上显示图像和问题时,会出现“阅读问题的时间”和从 10 到 0 的倒计时,然后是“回答的时间”和从 10 到 0 的倒计时。如果计时器结束并且没有回答问题并且图像会自动改变。但问题是,我可以做计时器,倒计时,在这之后它改变了问题,但我不知道如何把它放到标签中。如果在 Timer 中我执行类似 seconds-- label.setText(seconds) 的操作,则没有错误,但是当我启动应用程序时会出现很多异常。您能帮我如何将这个在计时器中每秒递减的变量放入 Label 吗?

public void setTimer() {
    timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            if(interval > 0)
            {
                timeElapsed.setText("Time to read the question: "+interval);
                System.out.println(interval);
                interval--; 
            }
            else
                timer.cancel();
        }
    }, 1000,1000);
}

现在我有这样的东西,在控制台中一切正常,倒计时从 10 到 0,但在场景中没有效果。

还有错误:

Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
at javafx.graphics/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:291)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:493)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at javafx.controls/javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:271)
at javafx.controls/javafx.scene.control.skin.LabeledSkinBase.lambda$new$11(LabeledSkinBase.java:219)
at javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$1(LambdaMultiplePropertyChangeListenerHandler.java:49)
at javafx.base/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
at javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
at javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
at javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
at javafx.base/javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.controls/javafx.scene.control.Labeled.setText(Labeled.java:147)
at gui.controller.StudentTestYesNoController$1.run(StudentTestYesNoController.java:40)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)

【问题讨论】:

标签: java javafx scenebuilder


【解决方案1】:

问题是您试图从应用程序以外的线程更改 UI。

这应该可以解决您当前实施的问题

public void setTimer() {
    timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            if(interval > 0)
            {
                Platform.runLater(() -> timeElapsed.setText("Time to read the question: "+interval));
                System.out.println(interval);
                interval--;
            }
            else
                timer.cancel();
        }
    }, 1000,1000);
}

此外,您可以查看有关 javafx 的特定内容 - Timeline

JavaFX periodic background task

【讨论】:

    【解决方案2】:

    加上mcwolf先生上面所说的,我认为你需要设置

    Platform.setImplicitExit(false);
    

    Platform.runLater(); 之前,以便每次调用任务时都会运行。

    【讨论】:

      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多