gpt4 book ai didi

c++ - 如何在 C++ 运行时更改 QML 对象的属性?

转载 作者:太空宇宙 更新时间:2023-11-04 12:41:10 25 4
gpt4 key购买 nike

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

我试过如下,但文本仍然是空的。

这是后端类:

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 实例并尝试访问像这样的值

BackEnd {
id: backend
}

Text {
...
text: backend.userFieldText
}

我这样注册类(class)。

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

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

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

编译有效,它运行但没有改变任何东西。我已经尝试将它放入 QML 代码的计时器中并每秒更新一次,但似乎没有任何效果。

最佳答案

您有以下错误:

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

  • QML 只接受存在于主线程中的对象,因此无法在另一个线程中创建后端对象,一种可能是您创建另一个存在于辅助线程中的对象并将数据传输到主线程通过信号,另一种可能性是使用 QThread 接受信号的创建并将其连接到 Backend 对象。

  • 您要在 QML 中进行绑定(bind)的属性必须可通过信号进行通知。

考虑到以上,一个例子如下:

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"

ma​​in.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++ - 如何在 C++ 运行时更改 QML 对象的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54189629/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com