jars121
jars121

Reputation: 1157

Routinely change QML property value from within a threaded c++ loop

I'm brand new to c++ and QML, and am struggling to call and run a threaded loop. I'd like to add an integer to a QML propery value every x milliseconds.

I'll omit my main.qml code for now, as I'm able to access the desired property; this question pertains more to c++.

void fn(QQuickItem x)
{
    for (;;)
    {
        std::this_thread::sleep_for(std::chrono.milliseconds(100));
        x->setProperty("value", x->property("value").toReal() + 10);
    }
}

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    //QScopedPointer<TachometerDemo> Tacho(new TachometerDemo);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    QQuickItem *item = engine.rootObjects().at(0)->findChild<QQuickItem*>
("circularGauge");

    thread t1(fn, item);

    return app.exec();
}

Any guidance on the most efficient means for achieving the above desired functionality would be appreciated. Whilst I'm currently testing on a win32 platform, a cross-platform approach is required.

Upvotes: 1

Views: 809

Answers (1)

Xplatforms
Xplatforms

Reputation: 2232

Better use Qt's event loop mechanism and SIGNAL/SLOTS. And QThreads if needed. Also if you need to update value in QML in msecconds duration don't do it over setProperty, this function call takes too long. You can update your value directly in QML using JS. But if you need to update QML value from C++ you can do it this way:

test.h

#include <QObject>
#include <QTimer>

class Test : public QObject
{
    Q_OBJECT
public:
    Test();
    Q_PROPERTY(int value READ value NOTIFY valueChanged)
    int value(){return this->m_value;}

signals:
    void valueChanged();

private slots:
    void timeout();

private:
    int      m_value;
    QTimer * m_timer;
};

test.cpp

#include "test.h"

Test::Test():m_value(0)
{
    this->m_timer = new QTimer(this);
    this->m_timer->setInterval(100);
    connect(this->m_timer, &QTimer::timeout, this, &Test::timeout);
    this->m_timer->start();
}

void Test::timeout()
{
    this->m_value += 10;
    emit valueChanged();
}

in your main.cpp

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty(QStringLiteral("Test"), new Test());

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

Somewhere in your QML:

Label 
{
    text: Test.value
    anchors.centerIn: parent
}

This is the fastest way to update QML value from C++

Upvotes: 2

Related Questions