J'ai quelques problèmes pour changer le texte d'une fenêtre QML dans Qt. J'ai un fichier C ++ qui appelle un thread et à partir de là, j'essaye de changer la valeur de l'étiquette de texte. Le thread fonctionne correctement mais la valeur de texte du QML ne change pas. Voici une partie de mon code:
main.cpp :
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" } }
Thread.cpp : p >
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 :
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(); }
Quelqu'un peut-il me dire pourquoi cela ne fonctionne pas? Où est mon erreur?
Merci!
3 Réponses :
Vous ne devez pas modifier l'interface utilisateur d'un autre thread. Utilisez plutôt le signal / slot.
Vous ne devez pas créer une classe enfant à partir de QThread
, également (créez un worker et déplacez-le dans un autre thread).
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(); }
Item { id: rooItem visible: true anchors.fill: parent signal change(string s); onChange: foobar.text = s Text { id: foobar text: "Empty" } }
Vous avez 2 erreurs:
Compte tenu de ce qui précède, la solution est:
thread.h
// ... 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 } // ...
thread .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.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 .qml
#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
Pour plus d'informations, lisez:
Vous utilisez le mauvais mécanisme pour mettre à jour une propriété qml, jetez un œil à < code> QQmlProperty pour la bonne manière. Vous pouvez également exporter une instance de QObject dans le moteur qml et lier la propriété text labels à une propriété de cet objet. Gardez toujours à l'esprit que qml / qt quick sont essentiellement des hacks. Il existe un moyen de mettre à jour l'interface graphique en toute sécurité à partir d'un thread non graphique sans utiliser de signaux. à la place, vous pouvez utiliser des événements pour effectuer le travail. p>
@TrebledJ Pour démarrer la thead, vous devez appeler la méthode start et elle invoquera la méthode run sur le thread approprié
En exécutant thread.start (), la méthode run () est appelée. Oui cela fonctionne. Je le sais parce que le message de débogage de la boucle while () est imprimé. La méthode run est donc appelée. Aussi, je téléchargerai le fichier .h que vous m'avez demandé.