多速度JProgressBar开发问题:指定进度处仅暂停当前进度条而非整个应用
解决Swing进度条暂停时UI卡死的问题
嘿,我懂你遇到的麻烦了——你在Swing的事件派发线程(EDT)里调用Thread.sleep(),直接把整个UI给卡死了对吧?这很正常,因为EDT负责处理所有的界面渲染和用户交互,你把它堵住的话,整个程序就完全没反应了。
问题根源
你的当前代码里,Timer的ActionListener是在EDT上执行的,当你调用Thread.sleep(1000)时,EDT被阻塞,所有UI更新和用户操作都停了,自然整个窗口僵住。
解决方案:用Swing Timer实现非阻塞暂停
我们可以用第二个Timer来处理暂停逻辑:当进度条到达指定值时,停止主进度更新的Timer,启动一个延时2秒的Timer,时间到了再重启主Timer。这样EDT不会被阻塞,UI依然能响应。
另外,如果你需要多个不同速度的进度条,每个进度条应该有独立的状态(计数器、步长)和Timer,这样它们的速度和暂停逻辑可以分开控制。
示例代码:单Timer控制多进度条(同速度)
import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; // 假设这是你的Sim1类的部分代码 public class Sim1 { private JProgressBar jjProgressBar; private JProgressBar jjProgressBar2; private JProgressBar jjProgressBar3; private JRadioButton jRadioButton1; public void initProgressBars() { Timer mainTimer; Timer pauseTimer; // 初始化暂停Timer:只执行一次,2秒后重启主Timer pauseTimer = new Timer(2000, e -> { mainTimer.start(); pauseTimer.stop(); }); pauseTimer.setRepeats(false); // 主进度更新Timer的监听器 ActionListener mainListener = new ActionListener() { int counter = 0; int delta = 1; final int min = 0; final int max = 100; @Override public void actionPerformed(ActionEvent ae) { if (!jRadioButton1.isSelected()) { return; // 单选按钮未选中时不更新 } counter += delta; // 处理进度条往返逻辑 if (counter < min || counter > max) { delta *= -1; } counter = Math.min(max, Math.max(min, counter)); // 更新所有进度条 jjProgressBar.setValue(counter); jjProgressBar2.setValue(counter); jjProgressBar3.setValue(counter); // 检查是否需要暂停(25/50/75时) if (counter == 25 || counter == 50 || counter == 75) { mainTimer.stop(); pauseTimer.start(); } } }; mainTimer = new Timer(100, mainListener); mainTimer.start(); } }
示例代码:多Timer控制独立进度条(不同速度)
如果要让每个进度条有不同的速度,给每个进度条单独创建Timer即可:
import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Sim1 { private JProgressBar jjProgressBar; private JProgressBar jjProgressBar2; private JProgressBar jjProgressBar3; private JRadioButton jRadioButton1; public void initProgressBars() { // 进度条1:速度快(100ms间隔) setupProgressBar(jjProgressBar, 100); // 进度条2:速度中等(200ms间隔) setupProgressBar(jjProgressBar2, 200); // 进度条3:速度慢(300ms间隔) setupProgressBar(jjProgressBar3, 300); } private void setupProgressBar(JProgressBar bar, int delay) { Timer barTimer = new Timer(delay, new ActionListener() { int counter = 0; int delta = 1; final int min = 0; final int max = 100; @Override public void actionPerformed(ActionEvent e) { if (!jRadioButton1.isSelected()) { return; } counter += delta; if (counter < min || counter > max) { delta *= -1; } counter = Math.min(max, Math.max(min, counter)); bar.setValue(counter); // 触发暂停逻辑 if (counter == 25 || counter == 50 || counter == 75) { barTimer.stop(); // 2秒后重启当前进度条的Timer new Timer(2000, pauseEvt -> barTimer.start()).start(); } } }); barTimer.start(); } }
关键要点
- 永远不要阻塞EDT:
Thread.sleep()、wait()等阻塞操作绝对不能在EDT里执行,这是Swing开发的核心原则。 - 用Swing Timer处理定时任务:Swing Timer的事件在EDT上执行,但启动/停止操作不会阻塞线程,是Swing中处理定时UI更新的正确方式。
- 独立状态管理:多个进度条需要各自的计数器、步长和Timer,才能实现不同速度的独立控制。
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

