c++ Qt processEvents()和while循环问题

b91juud3  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(328)

我正在用Qt(C++)编写一个应用程序,我有一个while循环,依赖于某个布尔变量,该变量在开始时被设置为true,当主部件析构函数被调用时,它被设置为false,以便在主部件关闭时中断循环。
下面是重现上述情况的示例代码。

//testwidget.h
#include <QWidget>
#include <QPushButton>
#include <QApplication>
#include <QLayout>

class testWidget : public QWidget
{
Q_OBJECT
public:
        testWidget(QWidget* parent = nullptr);
        ~testWidget();
        QPushButton* button;
        QApplication* application;
        QHBoxLayout* layout;
        bool run;
public slots:
        void start();
};

#include "testwidget.h"

testWidget::testWidget(QWidget* parent) : QWidget(parent)
{
    run = true;
    application = static_cast<QApplication*>(QApplication::instance());
    button = new QPushButton("BUTTON");
    layout = new QHBoxLayout(this);
    layout->addWidget(button);
    connect(button, SIGNAL(clicked()), this, SLOT(start()));
}

void testWidget::start()
{
    while(run)
    {
        application->processEvents();
    }
}

testWidget::~testWidget()
{
        run  = false;
}

#include <QApplication>
#include "testwidget.h"

int main(int argc, char *argv[ ])
{
        QApplication app(argc, argv);
        testWidget w;
        w.show();
        return app.exec();
}

所以当我点击按钮时,循环就开始了。但是如果我关闭小部件(点击“X”关闭按钮),程序就会继续运行(即使小部件消失了)。
因此,如果循环没有开始,程序正常关闭。
因此,如果循环正在运行,则不调用析构函数。
这可能取决于processEvents()方法跳过了析构函数的调用,但如何以干净的方式修复它呢?
目前我已经使用this->setAttribute(Qt::WA_DeleteOnClose);“解决”了它,但这是一种强迫。

yjghlzjz

yjghlzjz1#

通过对槽使用无限阻塞函数

connect(button, SIGNAL(clicked()), this, SLOT(start()));

你基本上阻塞了由app.exec();启动的事件循环,然后你解决了对application->processEvents();的恶意调用。processEvents确实会处理其他信号(小部件几何形状,点击X等),但是由于QPushButton::clicked触发的插槽永远不会返回,app.exec();也不会,这导致了你的小部件永远不会被破坏的情况。
将事件处理逻辑留给Qt,如果你想启动一些异步操作,比如帧捕获,在一个单独的线程中完成,然后立即从你的Slot返回。

void testWidget::start()
{
    _worker = std::async(std::launch::async, [this]() { captureLogic(); });
}

注意在你的异步函数中你不应该接触任何GUI元素。如果你想显示一个帧,发送信号让你的小部件知道它准备好了,并在主线程中显示它(连接的插槽将被主事件循环触发)。

相关问题