我在Qt中更改QML窗口的文本时遇到了一些问题。我有一个调用线程的C ++文件,从那里我试图改变文本标签的值。线程正在运行,但QML中的文本值没有变化。以下是我的代码的一部分:
main.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();
}
Thread.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;
}
template.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个错误:
考虑到上述解决方案是:
thread.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
thread.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;
}
}
main.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();
}
main.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
}
// ...
欲了解更多信息:
您不应该从另一个线程修改UI。请改用信号/插槽。您不应该从QThread
创建子类(也创建一个worker并在另一个线程中移动它)。
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引擎中,并将labels文本属性绑定到该对象的某个属性。请记住,qml / qt quick基本上都是黑客攻击。有一种方法可以在不使用信号的情况下从非gui线程安全地更新gui。相反,你可以使用events来完成工作。