从C++更新 QML 文本
Update QML text from C++
我在Qt中更改QML窗口的文本时遇到了一些问题。我有一个调用线程的C++文件,从那里我正在尝试更改文本标签的值。线程运行正常,但 QML 中的文本值未更改。下面是我代码的一部分:
主.cpp:
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///template.qml")));
QQuickItem *label = engine.rootObjects().at(0)->findChild<QQuickItem*>("myLabel");
thread2 thread(label);
thread.start();
}
线程.cpp:
thread2::thread2(QQuickItem *label) {
this->label = label;
}
void thread2::run() {
int test = 0;
char buffer[10];
int speed = 100;
while(1) {
speed++;
sprintf(buffer,"%d km/h",speed);
this->label->setProperty("text", QString(buffer));
QThread::msleep(1000);
qDebug()<<"tic: "<<buffer<<endl;
}
模板.qml:
Window {
id: window
visible: true
width: 360
height: 360
Component {
id: fruitDelegate
Row {
spacing: 10
Text { text: name }
Text { text: '$' + cost }
}
}
Text {
width: 99
height: 19
text: qsTr("Speed: ")
anchors.verticalCenterOffset: 1
anchors.horizontalCenterOffset: 0
anchors.centerIn: parent
objectName: "lab"
}
Text {
width: 38
height: 19
text: qsTr(" 0 ")
anchors.verticalCenterOffset: 1
anchors.horizontalCenterOffset: 46
anchors.centerIn: parent
objectName: "myLabel"
}
}
谁能告诉我为什么不起作用?我的错误在哪里?
谢谢!
您有 2 个错误:
- 您不应该从另一个线程更新GUI,run方法在另一个线程中执行,因此Qt不保证它正常工作。
- 不要将元素从 QML 导出到 C++,因为它会带来几个问题,因为很多时候不可能通过对象名获取对象,另一个不便之处是项目的生命周期由 QML 决定,因此在给定时刻它可以被消除,以便标签可以指向正在使用它的未保留内存, 等。相反,它将C++对象导出到 QML。
考虑到上述情况,解决方案是:
线程.h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
public:
Thread(QObject *parent=nullptr);
~Thread() override;
Q_SLOT void stop();
Q_SIGNAL void textChanged(const QString & text);
protected:
void run() override;
};
#endif // THREAD_H
线程.cpp
#include "thread.h"
#include <QDebug>
Thread::Thread(QObject *parent):
QThread(parent)
{
}
Thread::~Thread()
{
}
void Thread::stop()
{
requestInterruption();
wait();
}
void Thread::run()
{
int speed = 100;
QString text;
while(!isInterruptionRequested()) {
speed++;
text = QString("%1 km/h").arg(speed);
Q_EMIT textChanged(text);
QThread::msleep(1000);
qDebug()<<"tic: "<< text;
}
}
主.cpp
#include "thread.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Thread thread;
QObject::connect(&app, &QGuiApplication::aboutToQuit, &thread, &Thread::stop);
thread.start();
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("thread", &thread);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
主.qml
// ...
Text {
id: txt
width: 38
height: 19
text: qsTr(" 0 ")
anchors.verticalCenterOffset: 1
anchors.horizontalCenterOffset: 46
anchors.centerIn: parent
objectName: "myLabel"
}
Connections{
target: thread
onTextChanged: txt.text = text
}
// ...
有关更多信息,请阅读:
- https://doc.qt.io/qt-5/qtquick-bestpractices.html#interacting-with-qml-from-c
- https://doc.qt.io/qt-5/thread-basics.html#gui-thread-and-worker-thread
不应从其他线程修改 UI。请改用信号/插槽。 您也不应该从QThread
创建子类(创建一个工作线程并将其移动到另一个线程中)。
Item {
id: rooItem
visible: true
anchors.fill: parent
signal change(string s);
onChange: foobar.text = s
Text {
id: foobar
text: "Empty"
}
}
class Worker: public QObject
{
Q_OBJECT
public slots:
void run()
{
while(1) {
QThread::msleep(1000);
emit changed(QDateTime::currentDateTime().toString());
}
}
signals:
void changed(QString);
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QThread* th = new QThread();
Worker* worker = new Worker();
worker->moveToThread(th);
QObject::connect(th, &QThread::started, worker, &Worker::run);
th->start();
QQuickView view(QStringLiteral("qrc:/Main.qml"));
QObject* o = view.rootObject();
QObject::connect(worker, SIGNAL(changed(QString)), o, SIGNAL(change(QString)));
view.showMaximized();
return app.exec();
}
您使用错误的机制来更新 qml 属性,请查看QQmlProperty
以获取正确的方法。您还可以将 QObject 实例导出到 qml 引擎中,并将标签文本属性绑定到该对象的某个属性。永远记住,qml/qt quick本质上是黑客。有一种方法可以在不使用信号的情况下从非 gui 线程安全地更新 gui。相反,您可以使用事件来完成工作。
相关文章:
- 如何从C++代码中检索 QML 的文本字段中的文本?
- 如何将 qml 的文本转换为 float 和 int
- 在 qml 中多行时省略文本
- 从 QML 更好地控制文本光标
- 如何从另一个QML文件更改标签文本
- 如何在 QML 中显示来自 QTextDocument 的分页文本?
- Qt Quick 2 Qml:将文本准确地放在圆圈的中心
- 从C++更新 QML 文本
- 如何替换QT QML中的变体数组文本
- 从 Qt 5.2.1 C++更改 QML 文本框中的文本
- 如何使用从C++生成的关键事件更改 QML 文本字段文本属性
- 如何在Qt QML中以声明性方式更改文本的颜色
- 如何使用Blackberry 10中的Cascades中的Qt/qml/C++将一个qml文件中的标签文本从另一个qml
- 如何从C++修改QML文本
- 如何从TextInput在一个特殊的容器文本[诺基亚Qt Qml]
- Qt QML 如何格式化(突出显示)文本
- 如何用Qt中的QSyntaxHighlighter类在QML TextEdit上实现富文本逻辑
- QML文本元素上的dataChanged
- QML-如何在ListView上显示文本文件
- QML/D文本编辑器和基本注意事项