我有一个名为Data的类,这个类有一个带有从设备读取数据的循环的函数。循环永远不会停止读取数据。
为了这个例子,我们可以说类Data有以下代码:
class Data : public QObject
{
Q_OBJECT
public:
explicit Data(QObject *parent = nullptr){
genData();
}
//the job of this function is to always get data
void genData(){
while(true){
m_number++;
//somehow keep updating the value in QML and keep doing it?
}
}
private:
int m_number = 0;
};
所以,我需要做的是能够在main.qml中显示m_number,并在每次C ++更改时更新QML UI中的值。在这种情况下,循环正在递增m_number的值。
我有一些想法,我必须做些什么来完成这项工作,但我并不积极。 1.我知道我必须在不同的线程中运行该函数,以便它不会阻止程序的其余部分,并且我能够实现这一点。 2.我知道我必须实现Q_PROPERTY并且我也能够实现它,但它只显示Data :: m_number中的第一个值(初始值为0)。
我不知道的是如何使一切互动。我也不确定是否还需要实施其他任何东西。不过,我确信有很多东西我没有看到。我已经阅读了文档,但我只能理解我目前所处的观点。
我很感激任何人都可以提供的帮助和示例代码。谢谢。
答案 0 :(得分:3)
QThread
是一个管理低级别线程的类,更好的选择是使用QThreadPool
和QRunnable
。
QRunnable是一个具有将在某个线程上运行的方法的类,该类将传递Data类型的对象,并使用invokeMethod通过setter更新数据。
<强> runnable.h 强>
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include <QObject>
#include <QRunnable>
#include <QThread>
class Runnable : public QRunnable
{
int mNumber = 0;
QObject *mReceiver;
bool mRunning;
public:
Runnable(QObject *receiver){
mReceiver = receiver;
mRunning = false;
}
void run(){
mRunning = true;
while(mRunning){
mNumber++;
QMetaObject::invokeMethod(mReceiver, "setNumber",
Qt::QueuedConnection,
Q_ARG(int, mNumber));
QThread::msleep(10);
}
}
bool isRunning() const{
return mRunning;
}
void stop(){
mRunning = false;
}
};
#endif // RUNNABLE_H
使用QML交互C ++的一种方法是通过Q_PROPERTY
,因此在这种情况下将使用它,在Runnable
方法中我们将执行start()
的类从QML调用,为此我们将使用Q_INVOKABLE
。
<强> data.h 强>
#ifndef DATA_H
#define DATA_H
#include "runnable.h"
#include <QObject>
#include <QThreadPool>
class Data : public QObject
{
Q_OBJECT
Q_PROPERTY(int number READ number WRITE setNumber NOTIFY numberChanged)
public:
explicit Data(QObject *parent = nullptr):QObject(parent){
m_number = 0;
runnable = new Runnable(this);
}
~Data(){
runnable->stop();
}
Q_INVOKABLE void start(){
if(!runnable->isRunning())
QThreadPool::globalInstance()->start(runnable);
}
int number() const{
return m_number;
}
public slots:
void setNumber(int number){
if(number == m_number)
return;
m_number = number;
emit numberChanged(m_number);
}
signals:
void numberChanged(int);
private:
int m_number;
Runnable *runnable;
};
#endif // DATA_H
然后该类在main中注册,然后我们创建一个将建立连接的项目
<强>的main.cpp 强>
#include "data.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<Data>("com.example.data", 1, 0, "Data");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
<强> main.qml 强>
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import com.example.data 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Example")
ColumnLayout {
anchors.centerIn: parent
Button {
id: button
Layout.fillWidth: true
text: "start"
onClicked: data.start()
}
Text {
id: text1
text: data.number
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
}
}
Data{
id: data
}
}
该示例可在以下link中找到。