Swing通过后台线程实现页面更新

news2024/11/18 17:44:22

业务场景

在swing程序中,我们想实现一个随着任务的执行而同步更新组件的功能,如果在主线程(EDT)中直接执行任务并更新组件,则会导致组件只显示最终更新的状态的问题,这是因为EDT是单线程的,在执行耗时任务时会导致线程阻塞,无法即使更新swing组件。

为了实现这一功能,我们需要采用后台线程去执行任务,执行之后同步给EDT线程的方案,具体实现的话,我们可以使用 SwingWorker 这个函数在执行后台任务的同时实现组件的实时更新。

相关函数

下面我们介绍 SwingWorker中几个重要的函数:

  1. doInBackground() 方法

    • doInBackground()SwingWorker 中最重要的方法之一。
    • 在这个方法中,您可以执行耗时的任务,例如文件下载、数据处理或计算等。
    • 这个方法运行在后台线程,不会阻塞事件分发线程(EDT),因此可以确保用户界面的响应性。
  2. publish() 和 process() 方法

    • publish(V... chunks) 方法用于将数据块(chunk)发布到事件分发线程(EDT)以供处理。
    • process(List<V> chunks) 方法用于在事件分发线程(EDT)上处理已发布的数据块。
    • 这对方法一起工作,允许您在后台任务执行期间向事件分发线程发送数据,以便在用户界面上实时更新 Swing 组件,例如进度条或文本标签。
  3. done() 方法

    • done() 方法在后台任务完成后在事件分发线程(EDT)上执行。
    • 您可以在这个方法中处理任务完成后的任何收尾工作,例如清理资源、显示结果或触发其他操作。
  4. get() 方法

    • get() 方法用于获取后台任务的结果。
    • 它可以用于在任务完成后检索结果,但要注意,调用 get() 方法会阻塞当前线程,直到任务完成。
  5. cancel() 方法

    • cancel(boolean mayInterruptIfRunning) 方法用于取消后台任务。
    • 如果 mayInterruptIfRunning 参数为 true,则会尝试中断正在运行的任务。否则,它将尝试取消任务,但不会中断正在运行的任务。

这里我们需要注意SwingWorker声明了一个数据块chunk泛型数组来实现后台进程和EDT主进程的数据交互。

在我们下面的案例代码中,doInBackground()每次模拟完耗时操作后都会通过publish更新chunk数组,在proces函数中拿到这个数组的最后一位数据,实现实时更新。

案例代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class test {
    private JFrame frame;
    private JProgressBar progressBar;
    private JLabel progressLabel;

    public test() {
        frame = new JFrame("Progress Bar Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 100);
        frame.setLayout(new FlowLayout());

        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true); // 显示百分比
        frame.add(progressBar);

        progressLabel = new JLabel("Progress: 0%");
        frame.add(progressLabel);

        JButton startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startTask();
            }
        });
        frame.add(startButton);

        frame.setVisible(true);
    }

    private void startTask() {
        SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
            @Override
            protected Void doInBackground() throws Exception {
                for (int i = 0; i <= 100; i++) {
                    Thread.sleep(100); // 模拟耗时任务
                    publish(i); // 发布进度
                }
                return null;
            }

            @Override
            protected void process(java.util.List<Integer> chunks) {
                int latestProgress = chunks.get(chunks.size() - 1);
                progressBar.setValue(latestProgress);
                progressLabel.setText("Progress: " + latestProgress + "%");
            }

            @Override
            protected void done() {
                progressLabel.setText("Progress: 100% (Task completed)");
            }
        };

        worker.execute(); // 启动后台任务
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new test();
            }
        });
    }
}

效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1035978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【golang】深入理解Go语言垃圾回收(GC)

垃圾回收 垃圾回收版本1.3之前标记-清除&#xff08;mark and sweep&#xff09;算法标记-清除&#xff08;mark and sweep&#xff09;的缺点 版本1.5的三色并发标记法没有STW的三色标记法屏障机制强-弱 三色不等式插入屏障删除屏障 版本1.8的混合写屏障&#xff08;hybrid wr…

MQ - 25 RabbitMQ集群架构设计与实现

文章目录 导图集群构建节点发现元数据存储数据可靠性镜像队列仲裁队列安全控制传输加密身份认证资源鉴权可观测性总结导图 集群构建 集群构建由节点发现和元数据存储两部分组成。RabbitMQ 也是一样的实现思路。 节点发现 在节点发现方面,RabbitMQ 通过插件化的方式支持了多…

经典题记录 字符串相加/相乘

1. LeetCode 415 字符串相加 代码一&#xff1a;代码简短&#xff0c;但需要借助额外的一个string来保存结果&#xff0c;更占用内存。 class Solution { public:string addStrings(string num1, string num2) {string ans"";int size1num1.size();int size2num2.si…

php之导入导出csv文件

一、导入csv文件 1、创建导入页面 <!DOCTYPE html> <html lang"zh-CN"> <meta charset"UTF-8"> <head><title>文件提交表单</title> </head> <body> <form action"test5.php" method"…

嵌入式裸机架构的探索与崩塌

为什么会想着探索下嵌入式裸机的架构呢&#xff1f;是因为最近写了一个项目&#xff0c;项目开发接近尾声时&#xff0c;发现了一些问题&#xff1a; 1、项目中&#xff0c;驱动层和应用层掺杂在一起&#xff0c;虽然大部分是应用层调用驱动层&#xff0c;但是也存在驱动层调用…

6年Android开发前10月的总结,写给正在求职的安卓开发

进入大厂工作对许多人来说已经是一种挑战&#xff0c;但只要充分准备&#xff0c;很多问题都可以逐步解决。当然&#xff0c;运气也起到了一定的作用&#xff0c;但最终还是与自身的努力密不可分。运气是实力的一部分&#xff0c;因为自助者天助。 每到10月进行总结时&#xff…

华为ICT——第二章-数字图像处理私人笔记

目录 1&#xff1a;计算机视觉&#xff1a;​编辑 2&#xff1a;计算机视觉应用&#xff1a;​编辑 3&#xff1a;计算机视界核心问题&#xff1a;​编辑 4&#xff1a;相关学科&#xff1a; 5&#xff1a;计算机视觉与人工智能&#xff1a; 最成熟的技术方向是图像识别 6…

Django应用及分布式路由

Django应用及分布式路由 应用 应用在Django项目中一个完全独立的业务模块&#xff0c;可以包含自己的路由&#xff0c;视图&#xff0c;模板&#xff0c;模型 应用配置 在这里面添加你自定义的应用 INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.cont…

如何使用docker快速部署MinDoc文档系统

MinDoc是非常优秀的知识分享系统&#xff0c;但是很多刚接触的人会一脸懵逼&#xff0c;而且官方文档写的也并不清晰&#xff0c;所以和大家分享一下快速部署MinDoc的方法。 首先docker环境先自行安装好&#xff0c;这里不再赘述。 拉取docker镜像&#xff1a; docker pull …

解决 Github port 443 : Timed out

解决方法 打开代理页面 打开 设置 --> 网络与Internet --> 查找代理 记录下当前系统代理的 IP 地址和端口号 如上图所示&#xff0c;地址与端口号为&#xff1a;127.0.0.1:7890 注意修改成自己的IP和端口号 git config --global http.proxy http://127.0.0.1:7890 gi…

面试总结之微服务篇

一、概览 1、微服务常用组件 微服务给系统开发带来了诸多问题和挑战&#xff0c;如服务间通信和调用的复杂性、数据一致性和事务管理、服务治理和版本管理等&#xff0c;为解决应对这些问题和挑战&#xff0c;各种微服务组件应运而生微服务的常见组件和实现&#xff1a; 1…

解决react报错“JSX 表达式必须具有一个父元素“

现象如下&#xff1a; 原因&#xff1a; 新插入的dom元素跟已有的dom元素平级了&#xff0c;必须创建一个共有的根元素 解决办法&#xff1a; 使用<> </>标签作为根元素&#xff0c;把所有子元素包裹起来 <> ....原代码 </> 问题解决&#xff01;…

sun.reflect.annotation.TypeNotPresentExceptionProxy

解决方法 找到TypeNotPresentExceptionProxy类,在sun.reflect.annotation下在TypeNotPresentExceptionProxy方法里打断点debug项目,查看断点错误 如图是缺少redis依赖导致的错误 https://www.cnblogs.com/qingmuchuanqi48/p/11716706.html

Spring学习笔记7 Bean的生命周期

Spring其实就是一个管理Bean对象的工厂.它负责对象的创建,对象的销毁. 这样我们才可以知道在哪个时间节点上调用了哪个类的哪个方法,知道代码该写在哪里 Bean的生命周期之粗略5步 Bean生命周期的管理可以参考Spring的源码: AbstractAutowireCapableBeanFactory Bean的生命周期…

乐得瑞推出1拖2功率分配快充线方案,支持数据传输

随着PD3.1协议的市场应用越来越多&#xff0c;一些充电器的Type-C接口的输出功率达到百瓦及以上&#xff0c;如何充分利用好这类充电器设备&#xff0c;乐得瑞电子推出1拖2快充线缆解决方案&#xff0c;支持智能功率分配策略。 上图是乐得瑞1拖2功率分配快充线样线实物&#…

力扣刷题-链表-设计链表

题意&#xff1a; 在链表类中实现这些功能&#xff1a; get(index)&#xff1a;获取链表中第 index 个节点的值。如果索引无效&#xff0c;则返回-1。 addAtHead(val)&#xff1a;在链表的第一个元素之前添加一个值为 val 的节点。插入后&#xff0c;新节点将成为链表的第一个节…

哈希 -- 开散列(哈希桶)

拉链法 这里我们要是用string&#xff08;string来做key&#xff09;来取模&#xff0c;再增加一个模板参数&#xff0c;配一个取模的仿函数即可

leetcode 133. 克隆图

leetcode 133. 克隆图 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。 图中的每个节点都包含它的值 val&#xff08;int&#xff09; 和其邻居的列表&#xff08;list[Node]&#xff09;。 class Node { public int val;…

Flex布局是什么?

一、Flex布局是什么&#xff1f; Flex是Flexible Box的缩写&#xff0c;意为”弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性。 注意&#xff0c;设为Flex布局以后&#xff0c;子元素的float、clear和vertical-align属性将失效。 二、基本概念 采用Flex布局的元素…

基于JavaWeb(Servlet+jsp)的个人通讯录管理系统(含实验报告)

基于JavaWeb&#xff08;Servletjsp&#xff09;的个人通讯录管理系统&#xff08;含实验报告&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 本项目为简单的基于Javaweb实现的个人通讯录管理系统&#xff0c;实现主要功能为用户注册登录、首页展示、用户联…