gpt4 book ai didi

c++ - 在Qt中,发现所有窗口都关闭了,当使用QApplication::processEvents()时?

转载 作者:行者123 更新时间:2023-11-27 23:12:25 26 4
gpt4 key购买 nike

有一个 QApplication::lastWindowClosed() 信号。 Qt docs说:

This signal is emitted from QApplication::exec()
when the last visible primary window [...] is closed.

但是,我在循环中使用了 QApplication::processEvents() 而不是 QApplication::exec()。看到这个最小的例子。 (另存为qapp.h,必须以.h结尾,然后运行qmake -project && qmake && make)

#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMainWindow>

int exitprogram = 0;

class MyMainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void request_exit() {
qDebug() << "exit requested";
exitprogram = 1;
}
};

int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyMainWindow w;
QObject::connect(&app, SIGNAL(lastWindowClosed()),
&w, SLOT(request_exit()));
w.show();
while(!exitprogram)
{
app.processEvents(QEventLoop::AllEvents, 20);
}
}

如果最后一个这样的窗口正在关闭,还有没有好的方法可以查明甚至获得信号?

最佳答案

无论出于何种原因使用 processEvents 代替 exec 都是错误的。这两者是等价的。例如,exec() 将处理延迟删除事件,而 processEvents 则不会。正如您刚刚发现的那样,lastWindowClosed 信号也没有发出。这应该告诉你你做错了。

每次事件循环进行另一次迭代时,惯用的 Qt 方法是使用零超时计时器。这些是不使用操作系统资源的虚拟计时器,它们是内部 Qt 构造。

下面的示例说明了以下内容:

  1. QObject 中使用零超时计时器。

  2. 使用 State Machine Framework管理应用程序的状态。我们有三种状态:

    • sWindows 是应用程序窗口仍然显示时的状态。应用程序设置为在最后一个窗口关闭时退出。

    • sSetup 是最后一个窗口关闭时所达到的状态。在这种状态下,我们要求我们的 Object 发送它的通知信号,其中包含它执行零超时计时器的次数。这将在 message 标签(C++11 代码)或 count 标签(遗留代码)中设置正确的计数。状态机自动转换到以下状态。

    • sMessage 是消息标签显示时的状态,应用程序设置为在最后一个窗口关闭时退出。

状态机的使用导致声明式代码:您告诉状态机如何行为,而不是实现所有行为。您只需实现特定于您的应用程序且 Qt 尚未提供的行为。状态机管理的对象可以非常解耦,声明机器行为的代码是内聚的——它可以全部在一个函数中,而不是四处散布。这被认为是好的软件设计。

请注意,零超时计时器非常勤奋:它会强制您的处理程序代码在事件循环为空时持续执行。这将在 GUI 线程恰好执行的核心上强制使用 100% 的 CPU。如果您无事可做,则应该停止() 计时器。

Qt 5 C++11 代码

// https://github.com/KubaO/stackoverflown/tree/master/questions/close-process-19343325
#include <QtWidgets>

int main(int argc, char** argv)
{
QApplication app{argc, argv};
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};

int counter = 0;
auto worker = [&]{
counter++;
};
QTimer workerTimer;
QObject::connect(&workerTimer, &QTimer::timeout, worker);
workerTimer.start(0);

QStateMachine machine;
QState sWindows{&machine};
QState sSetup {&machine};
QState sMessage{&machine};

sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, &QGuiApplication::lastWindowClosed, &sSetup);

QObject::connect(&sSetup, &QState::entered, [&]{
workerTimer.stop();
message.setText(QString("Last window was closed. Count was %1.").arg(counter));
});
sSetup.addTransition(&sMessage);

sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);

machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}

Qt 4/5 C++11 代码

#include <QApplication>
#include <QLabel>
#include <QStateMachine>
#include <QBasicTimer>

class Object : public QObject {
Q_OBJECT
QBasicTimer m_timer;
int m_counter = 0;
protected:
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId())
m_counter ++;
}
public:
Object(QObject * parent = 0) : QObject{parent} {
m_timer.start(0, this);
}
Q_SLOT void stop() const {
m_timer.stop();
emit countedTo(m_counter);
}
Q_SIGNAL void countedTo(int) const;
};

int main(int argc, char** argv)
{
QApplication app{argc, argv};
Object object;
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};
QLabel count;

QStateMachine machine;
QState sWindows{&machine};
QState sSetup{&machine};
QState sMessage{&machine};

sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, "lastWindowClosed()", &sSetup);

object.connect(&sSetup, SIGNAL(entered()), SLOT(stop()));
count.connect(&object, SIGNAL(countedTo(int)), SLOT(setNum(int)));
sSetup.addTransition(&sMessage);

sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(&count, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);

machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}

#include "main.moc"

关于c++ - 在Qt中,发现所有窗口都关闭了,当使用QApplication::processEvents()时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19343325/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com