
这种情况很常见。你明明在循环里不断更新进度for (int i 0; i 100; i) { ui-progressBar-setValue(i); doWork(); }按理说应该看到1% 2% 3% ... 100%结果实际效果却是界面卡在那里半天不动。等任务结束以后进度条“啪”一下直接变成100%。到底谁把中间的进度吃掉了问题不在setValue()。它其实一直在执行。真正的问题是主线程一直没空刷新界面。Qt 的界面刷新本身也要经过事件循环。你在主线程里写一个很长的for (...)只要这个循环一直不结束Qt 就只能继续执行你的代码。鼠标事件、窗口重绘、进度条刷新都得先在后面排队。Qt 官方文档也说明很多界面更新并不是立即绘制而是等程序重新回到主事件循环后再处理。所以你虽然连续写了setValue(10); setValue(20); setValue(30);但用户根本看不到这些过程。等循环终于结束事件循环重新拿到执行机会这时候进度早就已经是100%于是界面直接显示最终结果。怎么解决核心思路只有一句别让一个大循环长时间霸占主线程。如果每一步任务都很轻可以把工作拆开一次只处理一点。比如用QTimerint current 0; QTimer *timer new QTimer(this); connect(timer, QTimer::timeout, this, []() mutable { doOneStep(); ui-progressBar-setValue(current); if (current 100) timer-stop(); }); timer-start(0);这样每处理一步代码都会把控制权还给事件循环。Qt 就有机会处理一步 ↓ 刷新界面 ↓ 处理下一步 ↓ 再刷新Qt 官方也提到0ms 的QTimer可以用来每次处理一个小任务让界面继续保持响应如果是真正的重任务更适合放到工作线程里。有些人会想到在循环里加QCoreApplication::processEvents();看起来确实可能“刷新了”。但这更像临时救急。因为它会在你的函数还没执行完时又去处理其他事件很容易带来新的状态和重入问题。真正耗时的任务还是应该拆任务或者放到工作线程。一句话总结进度条不动不一定是setValue()没生效而是主线程根本没机会把它画出来。循环里疯狂更新 UI 没用。先把事件循环还给 Qt。