Qt-GUI冷冻 我用C++编写了8个益智游戏的解题器,现在我试着用Qt给它一个GUI。

Qt-GUI冷冻 我用C++编写了8个益智游戏的解题器,现在我试着用Qt给它一个GUI。,c++,qt,user-interface,C++,Qt,User Interface,基本上,我有一个类型为“Board”的底层对象,它代表拼图的棋盘,我将GUI组织为QPushButton的网格。然后我有一个方法updateUI,它根据电路板将正确的文本关联到每个按钮。差不多 for(int i=0; i<Board::MATRIX_DIM * Board::MATRIX_DIM; i++) { m_buttons[i]->setText(m_values[i]); } 结果是GUI挂起,一段时间后,它只显示解决方案,完全跳

基本上,我有一个类型为“Board”的底层对象,它代表拼图的棋盘,我将GUI组织为QPushButton的网格。然后我有一个方法updateUI,它根据电路板将正确的文本关联到每个按钮。差不多

    for(int i=0; i<Board::MATRIX_DIM * Board::MATRIX_DIM; i++)
    {
        m_buttons[i]->setText(m_values[i]);
    }
结果是GUI挂起,一段时间后,它只显示解决方案,完全跳过移动

我错过了什么?谢谢大家!


另外,我认为我不需要为解算器设置不同的线程,因为我希望解算器在显示解算器之前运行。是否正确?

您正在暂停主线程(它也执行事件处理)并使其无法响应键盘/鼠标/窗口消息

您应该使用异步计时器操作而不是睡眠功能:使用延迟来延迟显示下一个解决方案,并避免消息长时间未应答。

实际上是
app.exec()
运行主循环,该循环处理所有事件,包括显示GUI。如果您想在此之前调用
solve()
,这没关系,但如果您想在
exec()
之前实际显示和更新GUI,这是错误的。我不确定这是否完全不可能,但这绝对不是正确的方法

有两种方法可以解决这个问题。更规范的方法是使用
QTimer
重新设计程序。然后一切都会顺利进行,反应迅速。但这有时会很乏味。不过,对你来说,这应该很容易。只需将结果保存在某个地方,并每1000秒使用
QTimer
对象调用一个插槽-它将与您的
Sleep()
具有相同的效果,但将保持所有响应

另一种解决方案是在
exec()
开始其作业后调用
solveGUI()
方法。例如,可以使用
QTimer::singleShot()

然后,在每次
Sleep()
之前,您应该调用
QApplication::processEvents()
,这基本上允许您临时屈服控制,处理所有挂起的事件,包括GUI更新。这种方法稍微容易一些,但它的性能较差,因为GUI仍然在每次
Sleep()时冻结。例如,如果用户想要退出应用程序,或者如果需要重新绘制窗口,这将导致令人不舒服的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);
...

}
...
void主窗口::等待(整数间隔){
QTime定时器=新的QTime;
timer.restart();
while(timer.appeased()

尚未测试-但应该可以工作(可能有一些cpu负载)

UI是基于事件的(这涉及到操作系统级别,不是Qt)。你需要重新设计你的求解函数,这样它就可以在求解后立即返回,而不是休眠;然后你可以设置一个计时器(它在UI线程上提供事件)来一次显示一个移动,而不占用UI线程。不知道我是否理解你关于重新设计我的求解函数所说的话。。。它所做的基本上是扩展搜索树的节点,直到它达到目标,并且它可以工作:平均只需要几毫秒。然后,在这之后,我想开始展示这些动作。我指的是您的
solveGUI
方法,很抱歉造成混淆。好的,如果需要更多帮助,我会尝试发回。谢谢不要使用
睡眠
。改用
QTimer
QApplication app(argc, argv);
MainWindow w;
w.show();
w.solveGUI();

return app.exec();
QTimer::singleShot(0, &w, SLOT(showGUI()));
return app.exec();
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);
...

}
...