2016-11-15 76 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