2016-11-15 135 views
1

我正在使用Qt創建一個顯示GUI並接受來自管道的輸入的小應用程序。阻止讀取管道的調用

如果管道沒有建立(或者,按照我的理解,如果沒有作家),調用fopen塊,甚至認爲它show()功能後,本應當是所謂的,沒有顯示的UI。

如何顯示用戶界面,然後調用fopen及相關代碼?只要我的窗口在屏幕上,我不在乎是否fopen塊。

我曾嘗試使用類似connect(this, SIGNAL(window_loaded), this, SLOT(setupListener()));的東西,但行爲保持不變。

任何提示?謝謝 !

的main.cpp

#include <QApplication> 

#include "metadataWindow.h" 

#include <sys/time.h> 
#include <sys/types.h> 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    metadataWindow window; 
    window.showFullScreen(); 
    window.setupListener(); 

    return app.exec(); 
} 

metadataWindow.cpp

metadataWindow::metadataWindow(QWidget *parent) : QWidget(parent) 
{ 
    this->setupUI(); // not shown here, but just basic QLabel stuff 
} 

void metadataWindow::setupListener() 
{ 
    const char *metadata_file = "/tmp/my-pipe-file"; 

    // vvvvv This here is blocking vvvvvv 
    FILE *fd = fopen(metadata_file, "r"); 

    pipe = new QTextStream(fd); 

    streamReader = new QSocketNotifier(fileno(fd), QSocketNotifier::Read, qApp); 
    QObject::connect(streamReader, SIGNAL(activated(int)), this, SLOT(onData())); 
    streamReader->setEnabled(true); 
} 

回答

2

X是異步的,基於消息的協議。 X顯示服務器和X客戶端程序不斷交換消息。一個X客戶端程序不只是推某種虛擬按鈕,繪製其窗口,並在一天內調用它,直到它想要改變窗口上的某些東西。在顯示服務器和客戶端程序之間沒有交換消息的唯一時間是顯示器上完全沒有任何事情發生。沒有鼠標指針移動。沒有任何展示活動。

顯示窗口的任務包括按順序執行的多個步驟。實際的窗口對象本身被創建。所有的子窗口都被創建。所有窗口都被映射。映射窗口導致X服務器向客戶端程序發送一系列的暴露事件,客戶端程序負責渲染暴露的窗口部分。所有這些都是在X顯示服務器和X客戶端程序之間交換的數百個消息序列完成的。

這就是QApplication::exec()調用的功能。它進入Qt的主事件循環,Qt庫相應地處理X顯示事件。在事件循環運行之前,不會有任何可見的顯示更改。

使用基於事件的基礎架構(如X/Qt)時,正確的設計模式也是基於事件的方法。你有兩個基本選項。

  1. 在新線程中執行阻塞應用程序邏輯,與進入Qt事件循環的主執行線程無關。這繞過並支持符合事件驅動設計模式的需求,並且使得可以執行幾乎普通的程序,而不會打擾Qt。

  2. 對於您自己的代碼,也可以使用事件驅動模型和非阻塞文件描述符。無法使用fopen()庫調用。相反,在非阻塞模式下,管道將爲open(),並且當打開文件系統管道的另一側時,管道可以選擇寫入。有關更多信息,請閱讀手冊頁面open()poll()。最後閱讀Qt關於QSocketNotifier類的文檔,該文檔解釋瞭如何讓Qt庫監視您自己的文件描述符上的事件(作爲其主事件循環的一部分),並調用您的代碼來處理讀取和寫入它們的任務。

當然,使用執行線程和套接字通知符的混合方法也是可能的。重要的一點是瞭解過程應該如何正確工作,並且永遠不要寫任何阻止Qt主事件循環的代碼。

+0

非常感謝您的非常清楚的解釋。我在非阻塞模式下使用'open()'進行了第二次路由,因此,我在第一次調用'onData()'時初始化了'QTextStream'管道(因爲我無法從'直接打開()')。這實際上工作得很好,我不認爲它會有任何缺點。 – tchap