我需要通过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)));
有了这个,我已经犯了同样的错误,而我已经将很多小部件连接到这个类而没有任何错误。 可能是什么问题?
当我在读者的构造函数中将主窗口(控制器)作为参数给出时,我有一个解决方案,并连接到这个,但如果可能的话,我会解释前一个问题。 我当前遇到的问题是信号发出良好但在应用程序结束后执行插槽(因此在线程执行结束后而不是在执行期间) 这不是本主题的主题,所以我们可以关闭这个。
答案 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)
我将您的问题解释为"我的应用程序在工作时没有响应"而不是"我的焦点跳到另一个窗口" - 如果你的意思不同,请评论。
您可以选择以下选项:
创建并运行后台QThread
来完成工作。当它有结果显示时,让它发出信号(使用Qt::QueuedConnection
- 默认值连接到您的小部件)。
当工作人员需要进行大量计算,或者需要在启动之前读取所有输入时,这是一个很好的解决方案。当目标系统具有可用的处理器而无需其他工作时,它可以很好地工作。
当某些输入可用时,使用QSocketNotifier
来表示您的GUI线程(请注意,该名称具有误导性 - 它实际上适用于所有类型的文件描述符,而不仅仅是套接字)。
当算法简单且增量时,这是合适的 - 即,如果可以快速读取和处理一小部分输入。
在您的算法中加入processEvents()
的定期调用:
auto *const dispatcher = QThread::currentThread()->eventDispatcher;
while (line = json.readLine()) {
doSomethingWith(line);
if (dispatcher)
dispatcher->processEvents();
}
除非您可以像这样修改算法,否则这不会起作用 - 如果循环是在别人的(关闭)代码中,那么您将需要其他解决方案之一。