QEventLoop 的使用兩例

熟悉的陌生人

Qt 是事件驅動的,所以當你用Qt的時候,幾乎時時刻刻和 QEventLoop 打交道、,只是你可能沒有意識到:

  • QCoreApplicaton::exec()
  • QApplication::exec()
  • QDialog::exec()
  • QThread::exec()
  • QDrag::exec()
  • QMenu::exec()
  • ...

在前面列出的這些常見函數的背後,都有各自的QEventLoop,可能是我們很少有機會想到自己顯式使用QEventLoop的緣故吧,對這個類似乎總是有些陌生。

在  如何讓 Qt 程序的 Sleep   和  QDialog 模態對話框與事件循環   兩個短文中,我們可以看到 QEventLoop 的使用。那麼?如何自己使用 QEventLoop 的,又有什麼用呢?

QEventLoop

Manual 中說的很簡潔

At any time, you can create a QEventLoop object and call exec() on it to start a local event loop. From within the event loop, calling exit() will force exec() to return.

在任何時候,你都可以創建一個QEventLoop的對象,然後調用它的exec() 來開始一個局部的事件循環。

看Manual容易讓人頭大,那麼,看例子吧:

讓主線程等待100ms?

直接sleep一下行麼,顯然,如果你的用戶不介意你的程序界面不響應用戶操作,沒問題!可是如果介意呢?

此時,開啓一個局部的事件循環,讓其執行100ms後自己退出,似乎很不錯。寫來看看:

QEventLoop eventloop;
QTimer::singleShot(100, &eventloop, SLOT(quit()));
eventloop.exec();
  • 創建事件循環
  • 啓動定時器,讓其100ms後觸發事件循環的quit()槽
  • 啓動事件循環

注:讓主線程等待有其他方法,此處略過。

窗口一閃而過?

不少人遇到過這個問題:在一個槽函數內創建了一個窗口對象,卻沒有看到窗口彈出來,或者看到窗口一閃而過。比如:

void XXXX::slot1()
{
    QDialog dlg;
    dlg.show()
}

當然,大家都知道原因:因爲到了後面的大括號處,dlg因爲出作用域,會被析構掉。解決方法很簡單,增大w的生存時間即可。比如:

  • 將 dlg 作爲類的成員,而不是函數的局部變量
  • 將 dlg 前面添加 static,作爲靜態成員
  • 將 dlg 用 new 分配到 heap 中
  • ...

能否用 QEventLoop 來解決呢?答案是,可以

 

void XXXX::slot1()
{
    QDialog dlg;
    dlg.show()
    QEventLoop loop;
    connect(&dlg, SIGNAL(finished(int)), &loop, SLOT(quit()));
    loop.exec(QEventLoop::ExcludeUserInputEvents);
}

恩至此,問題解決。其實,這也是 QDialog::exec() 內部所做的事情,只不過此處不是模態對話框而已。

博文索引  持續更新中。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章