定时器更新界面,线程报错

项目场景:

在javafx框架下使用线程更新UI的时候,出现无法正常更新UI。

问题代码如下:

cpp 复制代码
package clock;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class SimpleClock extends Application{

    public static void main(String[] args) {
        Application.launch();
    }
    public void start(Stage stage) {
        
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                
                
                        init(stage);
                        
                    
                });
            }
        }, 0, 1000); 
    
    }

    private void init(Stage stage){
        Calendar calendar = new GregorianCalendar();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        ClockPane cPane = new ClockPane(hour, minute, second);
        Scene scene = new Scene(cPane, 300, 300);
        stage.setTitle("Watch");
        stage.setScene(scene);
        stage.show();
    }

    
}

问题描述

运行程序之后,出现如下报错:

cpp 复制代码
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
        at javafx.graphics@22.0.1/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:294)
        at javafx.graphics@22.0.1/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:481)
        at javafx.graphics@22.0.1/javafx.stage.Stage.setScene(Stage.java:269)
        at clock.SimpleClock.init(SimpleClock.java:34)
        at clock.SimpleClock$1.run(SimpleClock.java:23)
        at java.base/java.util.TimerThread.mainLoop(Timer.java:571)
        at java.base/java.util.TimerThread.run(Timer.java:521)

原因分析:

checkFxUserThread

从出错日志看出checkFxUserThread这个方法在检查用户进程是否为UI线程,如果不是会抛出异常,这是因为为了使UI渲染不出现阻塞现象,不允许在子线程中进行UI操作。


解决方案:

可以使用javafx框架提供的runlater方法,实现切换到UI线程来执行更新UI的操作。

cpp 复制代码
    public void start(Stage stage) {
        
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        init(stage);
                        
                    }
                });
            }
        }, 0, 1000); 
    
    }
相关推荐
驭渊的小故事几秒前
从 JVM 底层看泛型:泛型擦除、Signature 属性与 Super Type Token 模式
java·开发语言·jvm
菜鸟小杰子3 分钟前
手动修改 Spring Boot 嵌套 JAR 包:大包小包隔离打包实战
java·jar
计算机编程-吉哥10 分钟前
计算机毕业设计 基于 SpringBoot + Vue 的剧本杀系统 Java毕业设计【任务书、开题报告、中期报告、论文、源码】
java·vue.js·spring boot·毕业设计·课程设计·计算机毕业设计选题
code2cat20 分钟前
【随笔】RAG语义缓存:问题很相似,答案就能直接复用吗
java·缓存·知识库·rag
Rain的Java大神之路42 分钟前
面了 50 个候选人,90% 都挂在 LeetCode 3 无重复字符的最长子串:滑动窗口的 5 个致命坑
java·后端·leetcode
西凉的悲伤43 分钟前
Jsoup 库 HTML 解析详解
java·前端·html·jsoup
十碗饭吃不饱1 小时前
Apache POI 踩坑:setFontFamily 二次设置字体不生效、样式残留问题深度解析
java·word·apache
我命由我123451 小时前
6-2.Python 异常处理 - 异常捕获(捕获指定异常、常见异常类型、异常信息)
java·运维·开发语言·python·http·https·java-ee
zaizai10071 小时前
STL深度剖析2
java·c++·算法
周厉2 小时前
WebSocket 使用场景与实现方法:Java + Vue3 全栈实战
java·websocket·vue3·websocket双向通讯