2010-02-19 13 views
20

Ich habe eine QApplication, die, abhängig von den Befehlszeilenparametern, manchmal kein GUI-Fenster hat, sondern einfach ohne GUI läuft. In diesem Fall möchte ich es ordnungsgemäß beenden, wenn STRG-C gedrückt wurde. Grundsätzlich sieht mein Code so aus:QApplication: Wie man elegant unter Ctrl-C herunterfährt

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

Dies funktioniert jedoch nicht. CTRL-C scheint abgefangen zu werden (die Anwendung wird nicht beendet), aber es wird auch nicht beendet. Was vermisse ich?

+0

[Dies ist sehr gut dokumentiert. Benutze die Dokumentation.] (Http://doc.qt.io/qt-5/unix-signals.html) –

Antwort

15

Da es nicht dokumentiert ist, sollte QApplication::watchUnixSignal nicht verwendet werden. Und vom Lesen des Codes wird es nicht richtig funktionieren, wenn der glib Event Dispatcher verwendet wird (was der Standard unter Linux ist).

Im Allgemeinen können Sie sicher Unix-Signale in Qt-Anwendungen zu fangen, müssen Sie nur ein wenig Code selbst schreiben. Es gibt sogar ein Beispiel in der Dokumentation - Calling Qt Functions From Unix Signal Handlers.

+0

Da es keine Möglichkeit gibt, auf dieser Seite etwas zu kommentieren, werde ich hier nur eine kurze Frage stellen, in der Hoffnung dass es für andere nützlich sein wird: Warum wurde ein Teil der Initialisierung in eine eigene statische Methode "static int setup_unix_signal_handlers()" separiert? –

+0

Ich sehe keinen Grund dafür, dass setup_unix_signal_handlers() statisch ist und als Teil einer Instanzmethode funktioniert. Die Dateideskriptorarrays können auch nicht statisch sein, jedoch nur, wenn Sie über C++ 11 oder eine größere Initialisierungssyntax verfügen. – rholmes

1

Ich habe nicht viel mehr über QApplication::watchUnixSignal Dokumentation außer einem one liner für Qt 4.0 gefunden; vor allem ist es nicht in späteren Versionen von Qt dokumentiert. Es sieht also so aus, als ob diese Funktionalität nicht beworben wird (und daher angenommen wird). Dabei ist der "Qt-Weg" natürlich nett, ich würde einfach wieder auf die signal system call zurückgreifen.

17

Es gibt möglicherweise eine Möglichkeit, dies nativ mit Qt zu tun - ich stocherte um die QKeySequence Dokumente für ein bisschen vor dem Aufgeben, aber Sie können einfach signal verwenden. Ich habe im Moment kein Qt/C++ - Setup auf meinem Rechner, aber ich habe die Python-Bindings.

import sys, signal 
from PyQt4 import QtGui 

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

sys.exit(app.exec_()) 

Dies funktioniert und wird die Anwendung schließen, wenn ich Ctrl-C tun. Deshalb glaube ich, dass Ihre Anwendung diesen Code anpassen könnte und es wäre etwas am Ende wie folgt:

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

Leider kann ich nicht kompilieren dies so wird es wahrscheinlich ein paar Korrekturen müssen, aber das sollten Sie die allgemeine Idee geben. Indem Sie den Handler SIG_DFL verwenden, weisen Sie Ihr Programm an, die Standardaktion zu verwenden, die mit Ctrl-C verknüpft ist.

1

Wie Jerkface Jones erwähnt, sieht das so aus, als ob es mit dem Standard-Event-Handler unter Linux nicht funktioniert.

Wenn Qt den rohen Unix (nicht-glib) Event-Handler verwendet, fängt und absorbiert Qt das^C sofort in seinem Signalhandler, aber das UnixSignal (int) -Signal wird nicht ausgegeben, bis Qt das Ereignis ausführt wird bearbeitet.

Wenn Code ausgeführt wird (anstatt im Leerlauf zu warten, bis Qt Signale sendet), müssen Sie QApplication::processEvents() für Qt aufrufen, um das Signal zu senden.

+1

Jerkface Jones? –

Verwandte Themen