QApplication:如何在Ctrl-C上正常关闭

时间:2010-02-19 23:49:51

标签: c++ qt unix

我有一个QApplication,根据命令行参数,有时实际上没有GUI窗口,但只是在没有GUI的情况下运行。在这种情况下,如果CTRL-C被击中,我想优雅地关闭它。基本上我的代码看起来像这样:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    ... // parse command line options

    if (no_gui) {
        QObject::connect(&app, SIGNAL(unixSignal(int)),
                         &app, SLOT(quit()));
        app.watchUnixSignal(SIGINT, true);
        app.watchUnixSignal(SIGTERM, true);
    }

    ... 

    return app.exec();
}

然而,这不起作用。 CTRL-C似乎被捕获(应用程序没有被杀死),但它也没有退出。我错过了什么?

5 个答案:

答案 0 :(得分:19)

可能有一种方法可以使用Qt本地执行此操作 - 我放弃了QKeySequence文档一段时间,但是你可以使用signal。我目前在我的机器上没有Qt / C ++设置,但我确实有Python绑定。

import sys, signal
from PyQt4 import QtGui

app = QtGui.QApplication(sys.argv)
signal.signal(signal.SIGINT, signal.SIG_DFL)

sys.exit(app.exec_())

当我执行Ctrl-C时,此功能将关闭应用程序。所以我相信你的应用程序可以调整这个代码,它最终会是这样的:

#include <signal.h>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    ... // parse command line options

    if (no_gui) {
        signal(SIGINT, SIG_DFL);
    }

    ... 

    return app.exec();
}

不幸的是,我无法编译它,所以它可能需要一些修复,但这应该给你一般的想法。使用SIG_DFL处理程序,您指示程序使用与Ctrl-C关联的默认操作。

答案 1 :(得分:17)

由于未记录,因此不应使用QApplication::watchUnixSignal。并且,通过阅读代码,使用glib事件调度程序(这是Linux上的默认设置)时,它将无法正常工作。

但是,通常你可以安全地在Qt应用程序中捕获Unix信号,你只需要自己编写一些代码。文档中甚至还有一个示例 - Calling Qt Functions From Unix Signal Handlers

答案 2 :(得分:1)

除了Qt 4.0的one liner之外,我没有找到更多关于QApplication::watchUnixSignal文档的内容。尤其是在Qt的更高版本中没有记录。因此,看起来这个功能没有被广告(因此假设)工作。虽然这样做“Qt方式”显然很好,但我只是回过头来使用signal system call

答案 3 :(得分:1)

正如Jerkface Jones所提到的,这似乎无法在Linux上使用默认事件处理程序。

如果Qt正在使用原始的Unix(非glib)事件处理程序,Qt会在其信号处理程序中立即捕获并吸收^ C,但在Qt执行事件处理之前不会发出unixSignal(int)信号

如果你有代码在运行(而不是等待Qt发送信号),那么你需要调用QApplication::processEvents()让Qt发送信号。

答案 4 :(得分:0)

您可以使用QApplication::instance()(或较短的宏版本qApp),它们至少在Qt4以后才可用:

#include <QApplication>
#include <csignal>

void sigHandler(int s)
{
    std::signal(s, SIG_DFL);
    qApp->quit();
}

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    std::signal(SIGINT,  sigHandler);
    std::signal(SIGTERM, sigHandler);

    return app.exec();
}