在后台读取文件以更新Qjsonvalue

时间:2016-06-21 11:40:29

标签: c++ qt

我需要通过JSON文件(实时更新)更新QWidget上字段的内容。我已经阅读了readLine()的函数readAll()QFile,但是当我尝试循环时:

while(true):
 jsfile.readLine()
 creation of objects, update of values, display etc ...

我把注意力集中在窗户上。但是我希望用我的按钮来控制应用程序,显然是要观察JSON值的演变。

我认为Qt管理自己的事件并将焦点放在当前窗口上,但就像我说的那样,情况并非如此。

当应用程序读取文件时(实时有新信息),是否有一个很好的解决方案(多线程可能)来使用我的窗口?

(使用约束“实时”我每次都无法读取整个文件而我无法选择此文件的格式)

更新

我尝试了线程方法。 所以,我选择将主线程实例创建到main(使用我的主窗口)并在此处连接。但是,当我运行程序时,我发现了这个错误:

  

没有匹配成员函数来调用'connect'

Reader reader;
QObject::connect(controler, SIGNAL(ready()),
                 reader, SLOT(received()));

根据这个错误,我认为原因主要是不继承Object,所以,我将连接和创建线程实例移动到我的主窗口。

Reader reader;
QObject::connect(reader, SIGNAL(newobject(QJsonObject)),
                 this, SLOT(displayJSON(QJsonObject)));

有了这个,我已经犯了同样的错误,而我已经将很多小部件连接到这个类而没有任何错误。 可能是什么问题?

更新2

当我在读者的构造函数中将主窗口(控制器)作为参数给出时,我有一个解决方案,并连接到这个,但如果可能的话,我会解释前一个问题。 我当前遇到的问题是信号发出良好但在应用程序结束后执行插槽(因此在线程执行结束后而不是在执行期间) 这不是本主题的主题,所以我们可以关闭这个。

2 个答案:

答案 0 :(得分:0)

您可以使用QThread(Qt文档:QThread)类创建一个线程,该线程将读取您的文件。主线程将执行您的GUI应用程序,它将在文件读取期间可用。 您可以在文档中找到一个用于创建线程的简单示例:

class WorkerThread : public QThread
{
    Q_OBJECT
    void run() Q_DECL_OVERRIDE {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }
signals:
    void resultReady(const QString &s);
};

void MyObject::startWorkInAThread()
{
    WorkerThread *workerThread = new WorkerThread(this);
    connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
    connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
    workerThread->start();
}

您可以为此目的修改此示例。例如,WorkerThread用于您的任务可能是这样的:

class WorkerThread : public QThread
{
    Q_OBJECT
    void run() Q_DECL_OVERRIDE {
        while(!stopFlag)
        {
            // read JSON file to QByteArray. Use QFile and QTextStream
            // use QJsonDocument to read JSON content
            // find what is new in JSON
            emit signalSomethingNew(/*parameters*/);
            QThread::currentThread()->msleep(/*timeout*/);
        }
    }
signals:
    void signalSomethingNew(/*parameters*/);
};

最后,您必须在QWidget上为signalSomethingNew(/*parameters*/)实施插槽并建立连接:

connect(yourThread, &WorkingThread::signalSomethingNew, youWidget, &YouWidget::yourSlot);

使用JSON数据:QJsonDocument

答案 1 :(得分:0)

我将您的问题解释为"我的应用程序在工作时没有响应"而不是"我的焦点跳到另一个窗口" - 如果你的意思不同,请评论。

您可以选择以下选项:

  1. 创建并运行后台QThread来完成工作。当它有结果显示时,让它发出信号(使用Qt::QueuedConnection - 默认值连接到您的小部件)。

    当工作人员需要进行大量计算,或者需要在启动之前读取所有输入时,这是一个很好的解决方案。当目标系统具有可用的处理器而无需其他工作时,它可以很好地工作。

  2. 当某些输入可用时,使用QSocketNotifier来表示您的GUI线程(请注意,该名称具有误导性 - 它实际上适用于所有类型的文件描述符,而不仅仅是套接字)。

    当算法简单且增量时,这是合适的 - 即,如果可以快速读取和处理一小部分输入。

  3. 在您的算法中加入processEvents()的定期调用:

    auto *const dispatcher = QThread::currentThread()->eventDispatcher;
    while (line = json.readLine()) {
        doSomethingWith(line);
        if (dispatcher)
            dispatcher->processEvents();
    }
    

    除非您可以像这样修改算法,否则这不会起作用 - 如果循环是在别人的(关闭)代码中,那么您将需要其他解决方案之一。