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

JProgressBar读取过程中不可见,仅加载完成后显示问题排查

问题分析与解决方案

嘿,这个问题我太熟了!你遇到的是Swing单线程模型的经典坑——事件派发线程(EDT)被阻塞了。

问题根源

Swing的所有UI更新和事件处理都在同一个线程(EDT)里完成。你在jButton3ActionPerformed这个事件回调方法里直接调用了inc(),而inc()里的Thread.sleep(1000)会把EDT死死卡住。这就导致:进度条的更新请求根本没机会被渲染到界面上,直到整个循环跑完、EDT被释放,UI才会一次性刷新到100%的状态。

解决方案:用SwingWorker分离耗时任务与UI更新

Swing专门提供了SwingWorker类来解决这种“后台耗时操作+实时UI更新”的场景,它能安全地在后台线程执行任务,同时在EDT里更新UI。

修改后的代码示例:

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) { 
    JFrame f = new JFrame("JProgressBar Sample"); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    Container content = f.getContentPane(); 
    progressBar = new JProgressBar(); 
    progressBar.setStringPainted(true); 
    Border border = BorderFactory.createTitledBorder("Reading..."); 
    progressBar.setBorder(border); 
    content.add(progressBar, BorderLayout.CENTER); 
    f.setSize(300, 100); 
    f.setVisible(true); 
    progressBar.setValue(0); 

    // 用SwingWorker执行后台任务
    new SwingWorker<Void, Integer>() {
        @Override
        protected Void doInBackground() throws Exception {
            // 这里是后台线程,执行耗时操作
            int i = 0;
            while (i <= 100) {
                publish(i); // 发送进度值到EDT
                Thread.sleep(1000);
                i += 20;
            }
            publish(100); // 确保最终进度到100%
            return null;
        }

        @Override
        protected void process(List<Integer> chunks) {
            // 这里在EDT里执行,安全更新UI
            int latestProgress = chunks.get(chunks.size() - 1);
            progressBar.setValue(latestProgress);
        }
    }.execute(); // 启动worker
}

为什么这样能行?

  • doInBackground():在独立的后台线程运行,里面的sleep不会阻塞EDT,进度条的更新请求能及时被处理。
  • publish():把进度值传递给process()方法,而process()是在EDT里执行的,完全符合Swing的UI更新规则。

额外提示

如果不想用SwingWorker,也可以手动开一个线程,但更新进度条时必须用SwingUtilities.invokeLater()把UI更新逻辑包装起来,比如:

new Thread(() -> {
    int i = 0;
    try {
        while (i <= 100) {
            final int progress = i;
            SwingUtilities.invokeLater(() -> progressBar.setValue(progress));
            Thread.sleep(1000);
            i += 20;
        }
        SwingUtilities.invokeLater(() -> progressBar.setValue(100));
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}).start();

不过SwingWorker更规范,还自带进度跟踪、任务取消等功能,推荐优先使用。

内容的提问来源于stack exchange,提问作者drunken-sailor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:58:22