QApplication: comment arrêter gracieusement sur Ctrl-C

J'ai une QApplication qui, en fonction des paramètres de ligne de commande, n'a parfois pas de fenêtre GUI, mais s'exécute simplement sans GUI. Dans ce cas, je veux l'arrêter gracieusement si CTRL-C a été frappé. Fondamentalement, mon code ressemble à ceci:

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

Cependant, cela ne fonctionne pas. CTRL-C semble être attrapé (l'application n'est pas tuée), mais elle ne sort pas non plus. Ce qui me manque?

21
demandé sur Martin 2010-02-20 02:49:50

4 réponses

, Comme il n'est pas documenté, QApplication::watchUnixSignal ne doit pas être utilisé. Et, de la lecture du code, il ne fonctionnera pas correctement lors de l'utilisation du répartiteur d'événements glib (qui est la valeur par défaut sur Linux).

Cependant, en général, vous Pouvez attraper en toute sécurité les signaux Unix dans les applications Qt, il vous suffit d'écrire un peu de code vous-même. Il y a même un exemple dans la documentation - appelant des fonctions Qt à partir de gestionnaires de signaux Unix .

17
répondu rohanpm 2016-05-29 20:39:57

Il peut y avoir un moyen de le faire nativement avec Qt - j'ai fouillé un peu les documents QKeySequence avant d'abandonner, mais vous pouvez simplement utiliser signal. Je n'ai pas de configuration Qt/C++ sur ma machine pour le moment, mais j'ai les liaisons Python.

import sys, signal
from PyQt4 import QtGui

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

sys.exit(app.exec_())

Cela fonctionne et fermera l'application quand je fais Ctrl-C. Donc, je crois que votre application pourrait adapter ce code et cela finirait par quelque chose comme ceci:

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

Malheureusement, je ne peux pas compiler ceci donc il aura probablement besoin d'un quelques corrections, mais cela devrait vous donner l'idée générale. En utilisant le gestionnaire SIG_DFL, vous demandez à votre programme d'utiliser l'action par défaut associée à Ctrl-C.

18
répondu swanson 2010-02-20 01:08:43

Je n'ai pas trouvé beaucoup plus sur la documentation QApplication::watchUnixSignal sauf pour un One liner pour Qt 4.0; en particulier, il n'est pas documenté dans les versions ultérieures de Qt. Ainsi, il semble que cette fonctionnalité n'est pas annoncée (et donc supposée) fonctionner. Tout en le faisant, la "manière Qt" est évidemment agréable, je retomberais simplement à utiliser l'appel système de signal à la place.

1
répondu bluebrother 2010-02-20 00:33:36

Comme Jerkface Jones l'a mentionné, cela semble ne pas fonctionner en utilisant le gestionnaire d'événements par défaut sur Linux.

Si Qt utilise le gestionnaire d'événements Unix (non-glib) brut, Qt interceptera et absorbera le ^c immédiatement dans son gestionnaire de signaux, mais le signal unixSignal(int) ne sera pas émis tant que Qt ne traitera pas les événements.

Si vous avez du code en cours d'exécution (plutôt que de tourner au ralenti en attendant que Qt envoie des signaux), vous devrez appeler QApplication:: processEvents () pour que Qt envoie signal.

1
répondu andrewffff 2010-02-20 15:56:35