我有一个Qt C ++程序,虽然它实际上并没有使用GUI(除了一些消息框弹出窗口),但使用了QApplication::exec()
方法(必要时运行事件循环并且可以服务整个信号/槽业务)。我还调用了QApplication::setQuitOnLastWindowClosed( false )
,因为否则程序会在用户解除其中一个消息框弹出窗口时立即结束。我不认为这会对我观察到的行为产生任何影响,但我还是提到它,以防万一。
当然,在某些时候,程序应该结束,并且我已经添加了对QApplication::exit()
的调用,导致Qt退出其事件循环,从而从QApplication::exec()
调用返回。根据{{3}},这正是应该发生的事情。
int QApplication :: exec()
进入主事件循环并等待直到调用exit(),然后 返回设置为exit()的值(如果exit()为0则为0) 通过quit()调用。
然而,在我的计划中,它并没有发生。我已经在调试器中跟踪了程序流程,我确信已调用QApplication::exit()
,但QApplication::exec()
似乎还没有想要返回。 :(
我使用Qt 5.4.1和MinGW 3.11(GCC编译器将自己标识为版本4.9.1)。我的电脑运行的是Windows 7企业版(64位),Service Pack 1.有谁知道我可能做错了什么?
编辑:Kuba Ober在评论中提到QApplication::exec()
可能没有返回,因为我的代码在某个地方阻塞了。我想发布主线程调用堆栈的屏幕截图,以证明主线程在此时深入到Qt的内部,并且我自己的代码实际上并不在控制之中。 / p>
Qt documention on the QApplication::exec() method
解决方案:好的,Rudolfs Bundulis'回答引导我解决问题的根源。我的程序中有一个小消息框弹出并要求用户执行某个操作(在这种情况下,打开一个与我的程序通信的外部设备)。为了使程序流程继续,没有必要忽略这个弹出窗口;只需打开外部设备就足够了,所以我忘了关闭消息框而不管它。后来,当QApplication::exit()
被调用时,Qt似乎破坏了消息框(或至少使其不可见),因此它不能再被解雇,正如Rudolfs Bundulis指出的那样,一个开放的消息框足以保持QApplication::exec()
返回。
答案 0 :(得分:2)
您描述的机制应该有效。这是一个小代码段,有两种方式可以按照您的方式终止QApplication
- 通过直接QApplication::quit()
广告位或QApplication::exit()
来电。两者似乎都有效。
QApplicationTerminator.h:
#pragma once
#include <QObject>
#include <QDebug>
#include <QApplication>
class QApplicationTerminator : public QObject
{
Q_OBJECT
public slots:
void quit()
{
qDebug() << "terminating QApplication\n";
QApplication::exit(0);
}
};
main.cpp中:
#include "qapplicationterminator.h"
#include <QApplication>
#include <QTimer>
#include <QDebug>
#include <QThread>
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
QApplicationTerminator terminator;
QTimer::singleShot(3000, &application, SLOT(quit()));
//QTimer::singleShot(3000, &terminator, SLOT(quit()));
application.setQuitOnLastWindowClosed(false);
auto result = application.exec();
qDebug() << "event loop exited\n";
return result;
}
我必须同意@KubaOber,你很可能要么在某个地方阻止。
由于您提到了对话框 - 对话框运行自己的事件循环,如果对话框的任何事件循环仍在运行(但是如果它们被正确使用则不会发生这种情况)主事件循环根本无法恢复控制并且无法退出。