簡體   English   中英

Qt - GUI 凍結

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM