[solved] setContextProperty not updated dynamically
-
Variables in C++ can be accessed in QML by applying QQmlContext::setContextProperty. I understand from the documentation that this was supposed to be dynamic, such that if value of the property is changed, the QML engine is notified so the display can be updated. But I'm finding the relationship is not dynamic. QML keeps the same value that was set at the time setContextProperty was used. Have I misunderstand how setContextProperty operates?
The problem can be easily demonstrated from a new project in QtCreator (standard QtQuick application), modified:
@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>int main(int argc, char *argv[])
{
QApplication app(argc, argv);QQmlApplicationEngine engine; QQmlContext *ctxt = engine.rootContext(); QString testString("one"); testString += " two"; ctxt->setContextProperty("testString", QVariant(testString) ); testString +=" three"; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); testString +=" four"; return app.exec();
}
@with main.qml
@
import QtQuick 2.3
import QtQuick.Controls 1.2ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("&Open") onTriggered: console.log("Open action triggered"); } MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } Text { text: testString anchors.centerIn: parent }
}
@With this code, the final value of testString is "one two three four". But setContextProperty is invoked at the point where testString="one two", and that is all that gets shown in the QML display. What did I miss?
-
Hi,
From the Docs:
bq. For maximum interoperability with QML, any property that is writable should have an associated NOTIFY signal that is emitted whenever the property value has changed.
In the above case since the property is already changed, the QML is able to get the changes. Further changes (i.e after loading QML) needs to be notified.
You will need to use Q_PROPERTY for that.
Check "this":http://qt-project.org/doc/qt-5/qtqml-cppintegration-exposecppattributes.html#exposing-properties example. -
I think I get it: the dynamic updating is not automatic, but needs to be actuated by a NOTIFY mechanism to signal that the value has changed.
Q_PROPERTY operates on class members (more specifically, QObject members). Am I right to understand that means there is no way to dynamically update general variables (C++ variables which are not members of a QObject subclass) ? I'd have to set up something like a singleton class instead.
-
bq. Am I right to understand that means there is no way to dynamically update general variables (C++ variables which are not members of a QObject subclass) ? I’d have to set up something like a singleton class instead.
If you know when the variable's value is going to change you can write a Q_INVOKABLE function which will return the new value and call this function from the QML. But can't be termed as dynamic.
Yes to take the full advantage of Binding and stuff it's better to create a class and set it as contextProperty as shown in the example. -
I've got it working now using a Q_PROPERTY member in a new subclass of QObject.
When I tried to access the field in QML it gave a thread error "QQmlEngine: Illegal attempt to connect to object that is in a different thread than the QML engine QQmlApplicationEngine". I seem to have fixed that by using the app object as a parent to make sure they're in the same thread.
@QApplication app(argc, argv);
MyQObject myqobject(&app);
...
ctxt->setContextProperty("myqobject", &myDebugObject-- );
@Thanks for your help!
-
You're Welcome. Have fun :)