简体   繁体   English

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

[英]QApplication: How to shutdown gracefully on Ctrl-C

I have a QApplication that, depending on command line parameters, sometimes doesn't actually have a GUI window, but just runs without GUI.我有一个QApplication ,根据命令行参数,有时实际上没有 GUI 窗口,但只是在没有 GUI 的情况下运行。 In this case, I want to shut it down gracefully if CTRL - C was hit.在这种情况下,如果CTRL - C被击中,我想优雅地关闭它。 Basically my code looks like this:基本上我的代码是这样的:

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();
}

However, this does not work.但是,这不起作用。 CTRL - C seems to be caught (the application doesn't get killed), but it also doesn't exit. CTRL - C似乎被捕获(应用程序没有被杀死),但它也没有退出。 What am I missing?我错过了什么?

There may be a way to do this natively with Qt -- I poked around the QKeySequence docs for a bit before giving up, but you can just use signal .可能有一种方法可以使用 Qt 本地完成此操作——我在放弃之前浏览了 QKeySequence 文档,但您可以只使用signal I don't have Qt/C++ setup on my machine at the moment, but I do have the Python bindings.目前我的机器上没有 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_())

This works and will close the application when I do Ctrl - C .这有效,并且会在我执行Ctrl - C时关闭应用程序。 So I believe that your application could adapt this code and it would end up something like this:所以我相信你的应用程序可以调整这段代码,它最终会是这样的:

#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();
}

Unfortunately, I cannot compile this so it will probably need a few fixes, but this should give you the general idea.不幸的是,我无法编译它,所以它可能需要一些修复,但这应该给你一个大致的想法。 By using the SIG_DFL handler you are instructing your program to use the default action associated with Ctrl - C .通过使用SIG_DFL处理程序,您可以指示您的程序使用与Ctrl - C关联的默认操作。

As it isn't documented, QApplication::watchUnixSignal shouldn't be used.由于没有记录,不应使用QApplication::watchUnixSignal And, from reading the code, it will not work properly when using the glib event dispatcher (which is the default on Linux).而且,从阅读代码来看,在使用 glib 事件调度程序(这是 Linux 上的默认设置)时,它将无法正常工作。

However, in general you can safely catch Unix signals in Qt applications, you just have to write a bit of the code yourself.但是,通常您可以安全地在 Qt 应用程序中捕获 Unix 信号,您只需要自己编写一些代码即可。 There is even an example in the documentation - Calling Qt Functions From Unix Signal Handlers .文档中甚至还有一个示例 - Calling Qt Functions From Unix Signal Handlers

You can use QApplication::instance() (or the shorter macro version qApp ), both available since at least Qt4:您可以使用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();
}

I haven't found much more about QApplication::watchUnixSignal documentation except for a one liner for Qt 4.0;我还没有更多关于发现QApplication::watchUnixSignal除了一个文件 一个衬垫Qt的4.0; especially it's not documented in later versions of Qt.尤其是在 Qt 的更高版本中没有记录。 Thus it looks like this functionality isn't advertised (and therefore supposed) to work.因此看起来这个功能没有被宣传(因此应该)工作。 While doing it the "Qt way" is obviously nice I'd simply fall back to using the signal system call instead.在这样做时,“Qt 方式”显然很好,我只是回退到使用信号系统调用

As Jerkface Jones mentioned, this looks like it doesn't work using the default event handler on Linux.正如 Jerkface Jones 所提到的,这看起来在 Linux 上使用默认事件处理程序不起作用。

If Qt is using the raw Unix (non-glib) event handler, Qt will catch and absorb the ^C right away in its signal handler, but the unixSignal(int) signal won't be emitted until Qt does event processing.如果 Qt 使用原始 Unix(非 glib)事件处理程序,Qt 将立即在其信号处理程序中捕获并吸收 ^C,但在 Qt 进行事件处理之前不会发出 unixSignal(int) 信号。

If you have code running (rather than idling around waiting for Qt to send signals), then you'll need to call QApplication::processEvents() for Qt to send the signal.如果您有代码正在运行(而不是闲着等待 Qt 发送信号),那么您需要调用QApplication::processEvents()让 Qt 发送信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM