[英]Qt - GUI freezing
我用 C++ 為 8 拼圖游戲編寫了一個求解器,現在我正在嘗試使用 Qt 為其提供 GUI。
基本上,我有一個“Board”類型的底層對象,它代表拼圖的板,並且我將 GUI 組織為 QPushButton 的網格。 然后我有一個方法 updateUI,它根據 Board 將正確的文本與每個按鈕相關聯。 就像是
for(int i=0; i<Board::MATRIX_DIM * Board::MATRIX_DIM; i++)
{
m_buttons[i]->setText(m_values[i]);
}
在另一種方法(solveGUI)中,我有
void MainWindow::solveGUI()
{
m_game->solve();
int solutionDepth = m_game->getSolutionDepth();
Move *solutionMoves = m_game->getSolutionMoves();
for(int i=0; i<solutionDepth; i++)
{
Move m = solutionMoves[i];
m_board.performMove(m); /* perform the move on the Board object */
updateUI(); /* should update the GUI so that it represents the Board */
Sleep(1000);
}
}
第一行(m_game->solve)需要一些時間。 然后我在 solutionMoves 中獲得執行的移動列表,我想要做的是在棋盤上顯示這些移動,在移動和下一個移動之間有一些延遲。 這個方法由我的 main 調用,它看起來像這樣:
QApplication app(argc, argv);
MainWindow w;
w.show();
w.solveGUI();
return app.exec();
結果是 GUI 掛起,一段時間后,它只顯示解決方案,完全跳過移動。
我錯過了什么? 謝謝!
PS 我認為求解器不需要不同的線程,因為我希望求解器在顯示解決方案之前運行。 這樣對嗎?
您正在停止主線程(它也進行事件處理)並使其無法響應鍵盤/鼠標/窗口消息。
您應該使用異步定時器操作而不是睡眠功能:使用QTimer來延遲顯示下一個解決方案並避免消息長時間未得到答復。
實際上是app.exec()
運行處理所有事件的主循環,包括顯示 GUI。 如果你想在這之前調用solve()
,沒關系,但如果你想在exec()
之前實際顯示和更新 GUI,那就錯了。 我不確定這是否完全不可能,但這絕對不是正確的方法。
有兩種方法可以解決。 更規范的方法是使用QTimer
重新設計程序。 然后一切都會順利且響應迅速。 但這有時會很乏味。 不過,就您而言,它應該很容易。 只需將結果保存在某處,然后每 1000 秒使用QTimer
對象調用一個插槽 - 它與您的Sleep()
具有相同的效果,但會使所有內容保持響應。
另一種解決方案是在exec()
開始其工作后調用您的solveGUI()
方法。 例如,可以使用QTimer::singleShot()
:
QTimer::singleShot(0, &w, SLOT(showGUI()));
return app.exec();
然后,在每個Sleep()
之前,您應該調用QApplication::processEvents()
,這基本上允許您臨時讓出控制,處理所有掛起的事件,包括 GUI 更新。 這種方法稍微容易一些,但它的效果較差,因為 GUI 仍然在每個Sleep()
處凍結。 例如,如果用戶想要退出應用程序,或者如果需要重新繪制窗口,則會導致不舒服的 GUI 延遲。
有一篇很好的文章介紹了在處理循環期間保持 GUI 響應的方法。 如果我認為這不是一個復雜的案例,只需插入QCoreApplication::processEvents();
在長處理循環中。
嘗試以下操作:
void MainWindow::Wait(int interval ) {
QTime timer = new QTime;
timer.restart();
while(timer.elapsed() < interval) {
QApplication::processEvents();
}
}
...
for(...) {
//wait 1 second (1000 milliseconds) between each loop run at first
Wait(1000);
...
}
...
尚未測試 - 但應該可以工作(也許有一些 CPU 負載)!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.