2010-02-19 12 views
20

Ho una QApplicazione che, a seconda dei parametri della riga di comando, a volte in realtà non ha una finestra GUI, ma funziona senza GUI. In questo caso, voglio chiuderlo con grazia se CTRL-C è stato colpito. Fondamentalmente il mio codice assomiglia a questo:QApplicazione: Come arrestare con garbo su 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(); 
} 

Tuttavia, questo non funziona. CTRL-C sembra essere catturato (l'applicazione non viene uccisa), ma non esce. Cosa mi manca?

+0

[Questo è molto ben documentato. Usa la documentazione.] (Http://doc.qt.io/qt-5/unix-signals.html) –

risposta

15

Poiché non è documentato, non utilizzare QApplication::watchUnixSignal. E, leggendo il codice, non funzionerà correttamente quando si usa il glib event dispatcher (che è il default su Linux).

Tuttavia, in generale si può in grado di catturare in modo sicuro i segnali Unix nelle applicazioni Qt, è sufficiente scrivere un po 'del codice da soli. C'è anche un esempio nella documentazione - Calling Qt Functions From Unix Signal Handlers.

+0

Dato che non c'è modo di commentare questa pagina, farò solo una breve domanda qui, nella speranza che sarà utile per gli altri: perché parte dell'inizializzazione è stata separata nel suo stesso metodo statico "static int setup_unix_signal_handlers()"? –

+0

Non vedo alcun motivo perché setup_unix_signal_handlers() sia statico e funziona correttamente come parte di un metodo di istanza. Gli array di descrittori di file possono anche essere non statici, ma solo se si ha una sintassi di inizializzazione C++ 11 o superiore. – rholmes

1

Non ho trovato molto altro sulla documentazione QApplication::watchUnixSignal ad eccezione di one liner per Qt 4.0; specialmente non è documentato nelle versioni successive di Qt. Quindi sembra che questa funzionalità non sia pubblicizzata (e quindi supposta) per funzionare. Mentre lo faccio il "modo Qt" è ovviamente bello, mi piacerebbe semplicemente tornare a utilizzare il signal system call invece.

17

Potrebbe esserci un modo per farlo in modo nativo con Qt - Ho cercato un po 'i documenti di QKeySequence prima di arrendermi, ma puoi semplicemente usare signal. Al momento non ho l'installazione Qt/C++ sulla mia macchina, ma ho i binding Python.

import sys, signal 
from PyQt4 import QtGui 

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

sys.exit(app.exec_()) 

Questo funziona e si chiuderà l'applicazione quando lo faccio Ctrl-C. Quindi credo che l'applicazione potrebbe adattare questo codice e che sarebbe finita o meno così:

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

Purtroppo, non riesco a compilare questo modo sarà probabilmente bisogno di alcune correzioni, ma questo dovrebbe darvi l'idea generale. Utilizzando il gestore SIG_DFL si sta istruendo il programma per utilizzare l'azione predefinita associata a Ctrl-C.

1

Come menzionato da Jerkface Jones, sembra che non funzioni utilizzando il gestore di eventi predefinito su Linux.

Se Qt sta usando il gestore di eventi Unix (non-glib) grezzo, Qt catturerà e assorbirà il^C immediatamente nel suo gestore di segnale, ma il segnale unixSignal (int) non verrà emesso finché Qt non si verifica in lavorazione.

Se il codice è in esecuzione (anziché rimanere inattivo in attesa che Qt invii segnali), è necessario chiamare QApplication::processEvents() per Qt per inviare il segnale.

+1

Jerkface Jones? –

Problemi correlati