在 Qt 應用中,若於 for 或 while 迴圈內連續載入圖片至 QGraphicsView,主事件迴圈被佔用,導致介面凍結:按鈕點擊無回應、視窗無法拖動、甚至被視為「未回應」。
QCoreApplication::processEvents()呼叫此靜態函數可讓 Qt 處理佇列中待處理的事件(重繪、滑鼠、鍵盤、定時器等),讓 UI 保持流暢。
// 1. 宣告暫停標誌(建議為成員變數)
bool m_pauseRequested = false;
// 2. 在迴圈內定期呼叫 processEvents 並檢查標誌
for (int i = 0; i < totalFrames; ++i) {
// 處理 UI 事件(重繪、按鈕點擊等)
QCoreApplication::processEvents(QEventLoop::AllEvents, 10); // 可選限制處理時間 10ms
// 檢查暫停請求
if (m_pauseRequested) {
// 進入等待迴圈,直到標誌被清除
while (m_pauseRequested) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
QThread::msleep(20); // 降低 CPU 佔用
}
}
// 正常載入幀資料...
loadFrame(i);
}
// 3. 暫停按鈕的槽函數
void onPauseClicked() { m_pauseRequested = true; }
// 4. 繼續按鈕的槽函數
void onResumeClicked() { m_pauseRequested = false; }
processEvents 內部會遞迴進入事件迴圈,若在槽函數中再次呼叫耗時操作,易導致堆疊溢位或死鎖。僅處理輕量 UI 更新。QEventLoop::ExcludeUserInputEvents:若不想在處理期間響應滑鼠/鍵盤,可排除使用者輸入事件。QThread + 訊號/槽:將耗時載入移至工作執行緒,主執行緒專司 UI,透過 QMetaObject::invokeMethod 或訊號傳遞進度。這是更符合 Qt 架構的做法,適合複雜場景。QTimer 每幀觸發載入一張圖,完全避免阻塞迴圈,程式碼更簡潔。class FrameLoader : public QObject {
Q_OBJECT
int m_current = 0, m_total = 0;
QTimer m_timer;
public:
FrameLoader() {
connect(&m_timer, &QTimer::timeout, this, &FrameLoader::loadNextFrame);
}
void start(int total) {
m_total = total; m_current = 0;
m_timer.start(16); // 約 60 FPS
}
private slots:
void loadNextFrame() {
if (m_current >= m_total) { m_timer.stop(); emit finished(); return; }
if (m_pauseRequested) return; // 暫停時直接跳過
loadFrame(m_current++);
emit progressChanged(m_current, m_total);
}
signals:
void progressChanged(int cur, int tot);
void finished();
};
簡單場景用 processEvents() + 標誌位即可快速解決凍結;長期專案建議採用執行緒或定時器模式,確保架構清晰、擴充性佳。