如何在C ++中的运行时更改QML对象的属性? [英] How to change properties of a QML Object during runtime in C++?

查看:52
本文介绍了如何在C ++中的运行时更改QML对象的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在运行时更改QML对象的文本.

I want to change the text of a QML Object during runtime.

我尝试了以下操作,但是文本仍然为空.

I tried it as following, but the text just stays empty.

这是BackEnd类:

This is the BackEnd class:

class BackEnd : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString userFieldText READ userFieldText WRITE setUserFieldText)
public:
    explicit BackEnd(QObject *parent = nullptr);

    QString userFieldText();
    void setUserFieldText(QString &username);
private:
    QString _userFieldText;
};

在qml文件中,我包含window.backend,创建一个新的BackEnd实例并尝试访问类似的值

In the qml file, I include window.backend, create a new BackEnd instance and try to access the values like

BackEnd {
 id: backend
}

Text {
 ...
 text: backend.userFieldText
}

我像这样注册课程.

qmlRegisterType<BackEnd>("window.backend", 0, 1, "BackEnd");

在一个我想更改对象的单独线程中,我创建了BackEnd类的实例并调用setter函数.

In a seperate thread where I would like to change the objects I create an instance of the BackEnd class and call the setter function.

BackEnd backend;
QString user("set by backend");
backend.setUserFieldText(user);

编译有效,它可以运行,但不会更改任何内容.我已经尝试过将其放入QML代码的计时器中,并每秒进行更新,但似乎无济于事.

Compilation works, it runs but does not change anything. I already tried putting it in a timer in the QML code and updating it every second but nothing seems to work.

推荐答案

您遇到以下错误:

  • 正如您所指出的,您已经在一个线程中创建了一个 Backend 实例,并在QML中创建了另一个实例,因此,对一个实例的状态进行修改不会对另一个实例进行修改.在这些情况下,如果要使用C ++和QML创建对象,最好使用 setContextProperty()创建上下文属性.

  • As you point you have created an instance of Backend in one thread, and another instance in QML, so the modification of the state of one instance does not modify the other instance. In these cases where you want to have an object in C++ and QML it is better to create a context-property with setContextProperty().

QML仅接受存在于主线程中的对象,因此不能在另一个线程中创建Backend对象,一种可能是您创建了另一个存在于辅助线程中的对象并将数据传输到主线程通过信号,另一种可能性是使用接受代码创建的 QThread 并将其连接到 Backend 对象.

QML only accepts objects that live in the main thread so the Backend object can not be created in another thread, one possibility is that you create another object that lives in the secondary thread and transmits the data to the main thread by signals, another possibility is to use QThread that accepts the creation of signals and connect it to the Backend object.

要在QML中绑定的属性必须通过信号通知.

The properties that you want to do binding in QML must be notifiable through a signal.

考虑到上述情况,下面是一个示例:

Considering the above, an example is the following:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QThread>
class BackEnd : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString userFieldText READ userFieldText WRITE setUserFieldText NOTIFY userFieldTextChanged)
public:
    explicit BackEnd(QObject *parent = nullptr):
        QObject(parent){}
    QString userFieldText() const {
        return _userFieldText;
    }
    void setUserFieldText(const QString &username){
        if(userFieldText() == username) return;
        _userFieldText = username;
        emit userFieldTextChanged();
    }
signals:
    void userFieldTextChanged();
private:
    QString _userFieldText;
};
class WorkerThread: public QThread
{
    Q_OBJECT
public:
    using QThread::QThread;
    ~WorkerThread() override {
        requestInterruption();
        quit();
        wait();
    }
signals:
    void textChanged(const QString &);
protected:
    void run() override{
        while (!isInterruptionRequested()) {
            emit textChanged(QString("set by backend: %1 ").arg(counter));
            QThread::msleep(100);
            counter++;
        }
    }
private:
    int counter = 0;
};
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    BackEnd backend;
    WorkerThread thread;
    QObject::connect(&thread, &WorkerThread::textChanged, &backend, &BackEnd::setUserFieldText);
    thread.start();
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("backend", &backend);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}
#include "main.moc"

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Text {
        anchors.centerIn: parent
        text: backend.userFieldText
    }
}

这篇关于如何在C ++中的运行时更改QML对象的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆