2010-02-19 93 views
20

我有一個QApplication,根據命令行參數,有時實際上並沒有GUI窗口,但只運行沒有GUI。在這種情況下,如果CTRL-C被擊中,我想優雅地關閉它。基本上我的代碼如下所示:QApplication:如何正常關閉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似乎被捕獲(應用程序不會被殺死),但它也不會退出。我錯過了什麼?

+0

[這是非常有據可查的。使用文檔。](http://doc.qt.io/qt-5/unix-signals.html) – 2015-09-12 15:32:55

回答

15

由於沒有記錄,QApplication::watchUnixSignal不應使用。而且,通過閱讀代碼,在使用glib事件分派器(這是Linux上的默認設置)時,它將無法正常工作。

但是,一般來說你可以在安全地捕捉到Qt應用程序中的Unix信號,你只需要自己編寫一些代碼。在文檔中甚至有一個例子 - Calling Qt Functions From Unix Signal Handlers

+0

由於沒有辦法評論該頁面,我只想在這裏提出一個簡短的問題,希望它會對其他人有用:爲什麼部分初始化被分離出它自己的靜態方法「static int setup_unix_signal_handlers()」? – 2014-03-06 23:26:53

+0

我看不到任何setup_unix_signal_handlers()爲靜態的原因,並且它可以作爲實例方法的一部分正常工作。文件描述符數組也可以是非靜態的,但前提是您擁有C++ 11或更高版本的初始化語法。 – rholmes 2016-11-28 14:00:57

1

我還沒有找到關於QApplication::watchUnixSignal文檔的更多信息,但是對於Qt 4.0,one liner除外;尤其是它在Qt的後續版本中沒有記錄。因此,它看起來像這個功能沒有廣告(因此應該)工作。雖然這樣做「Qt的方式」顯然是不錯的,我只是回到使用signal system call來代替。

17

可能有一種方法可以使用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

正如Jerkface Jones提到的,這看起來好像在Linux上使用默認事件處理程序不起作用。

如果Qt使用原始Unix(非glib)事件處理程序,Qt將在其信號處理程序中立即捕獲並吸收^ C,但直到Qt發生事件時纔會發出unixSignal(int)信號處理。

如果你的代碼正在運行(而不是等待Qt發送信號),那麼你需要調用QApplication::processEvents()來讓Qt發送信號。

+1

Jerkface Jones? – 2015-03-10 21:03:02