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

Java中如何通过次级类数据更新Swing进度条?

Swing进度条实现方案(无需迁移Secondary类代码)

核心问题说明

你的原有代码直接在事件调度线程(EDT)中执行Secondary.writeInfo(),会导致界面卡死,进度条无法实时更新。解决的核心是把耗时操作移到后台线程,同时安全地在EDT中更新Swing组件,且最小改动Secondary类代码。


具体改造步骤

1. 给Secondary类添加进度回调(最小侵入式修改)

不需要迁移业务逻辑,仅新增一个回调接口来传递进度:

public class Secondary {
    private String info;
    public int progress;
    
    // 新增进度回调接口
    public interface ProgressListener {
        void onProgressUpdate(int progress);
    }
    private ProgressListener listener;

    public Secondary(){
        info = "";
    }

    // 重载方法,接收进度监听器
    public String writeInfo(int n, ProgressListener listener) {
        this.listener = listener;
        return writeInfo(n);
    }
    
    public String writeInfo(int n){
        for(int i=1; i<=n; i++) {
            info += " bla";
            progress = 100*i/n;
            // 有监听器时通知进度更新
            if(listener != null) {
                listener.onProgressUpdate(progress);
            }
            // 模拟耗时操作(实际业务可删除)
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        return info;
    }
}

2. 修改Primary类,用SwingWorker处理后台任务

使用Swing官方推荐的SwingWorker实现后台执行+EDT安全更新:

import javax.swing.*;

public final class Primary {
    private JPanel primaryPanel;
    private JProgressBar progressBar;
    private JTextArea textArea;
    
    public Primary(){
        createPanel();
    }
    
    public void createPanel() {
         primaryPanel = new JPanel();
         primaryPanel.setSize(333, 333);
         
         // 给文本域加滚动条,避免内容溢出
         textArea = new JTextArea(5, 20);
         primaryPanel.add(new JScrollPane(textArea));
         
         progressBar = new JProgressBar(0, 100);
         progressBar.setStringPainted(true); // 显示百分比文本
         primaryPanel.add(progressBar);
         
         // 启动后台任务执行耗时操作
         startBackgroundTask();
         
         primaryPanel.setVisible(true);
    }

    private void startBackgroundTask() {
        SwingWorker<String, Integer> worker = new SwingWorker<>() {
            @Override
            protected String doInBackground() throws Exception {
                Secondary secondary = new Secondary();
                // 传入进度监听器,将进度发送到process方法
                return secondary.writeInfo(11, progress -> publish(progress));
            }

            @Override
            protected void process(java.util.List<Integer> chunks) {
                // 此方法在EDT执行,安全更新进度条
                int latestProgress = chunks.get(chunks.size() - 1);
                progressBar.setValue(latestProgress);
            }

            @Override
            protected void done() {
                // 任务完成后更新文本域
                try {
                    textArea.setText(get());
                } catch (Exception e) {
                    textArea.setText("任务执行出错: " + e.getMessage());
                }
            }
        };
        worker.execute(); // 启动后台线程
    }
    
    public JPanel getPanel(){
        return primaryPanel;
    }
}

3. 可选优化(GUI类)

把mainFrame.setSize(222, 222)改成mainFrame.pack(),让窗口自适应组件大小,避免内容被截断。


方案优势

  • 无代码迁移:仅对Secondary类做了极小修改,原有业务逻辑完全保留
  • 界面不卡顿:耗时操作在后台线程执行,不阻塞EDT
  • 线程安全:所有Swing组件的更新都在EDT中完成,符合Swing线程规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:47:45