QQmlPropertyMap, Unable to assign [undefined] to ....
-
Hello
I'm populating a QQmlPropertyMap dynamically;
m_propertyMap.insert(node.key(), 0);
The value is updated in an other function (nodeValueUpdate) connected to a signal "dataChangeOccured";
QObject::connect(m_nodes.value(node.key()).data(), &QOpcUaNode::dataChangeOccurred, [=](QOpcUa::NodeAttribute attr, QVariant value) { nodeValueUpdate(attr, value, node.key()); });
void opcClient::nodeValueUpdate(QOpcUa::NodeAttribute attr, const QVariant &value, const QString &key) { Q_UNUSED(attr); QByteArray key_ba = key.toLatin1(); const char *key_ch = key_ba.data(); if (m_propertyMap.contains(key_ch)) m_propertyMap.insert(key_ch, value); }
In main.cpp, the propertymap is made available to QML:
engine.rootContext()->setContextProperty("opcMap", opcclient.getPropertyMap());
I can then access the properties loaded in the constructor in said class with "opcMap.PropertyKeyHere".
My problem is that I'm getting errors/warnings saying "Unable to assign [undefined] to bool, double, QString" etc... The data is displayed correctly in my program tho. How to fix this? -
Maybe you assign the values before m_propertyMap is populated with values? Can you narrow the warnings down to a single line or component of QML code and show it to us?
-
The "flow" goes like this starting in the constructor of my class:
- myClass Constructor called: Load and parse external node-configuration for property map, register qml type, call myClass::connectToEndpoint
- myClass::connectToEndpoint: create the opcua client, connect QOpcUaClient::stateChanged to myClass::clientStateHandler, call QOpcUaClient::connectToEndPoint which'll presumably cause myClass::clientStateHandler to be called due to QOpcUaClient::stateChanged-signal.
- myClass::clientStateHandler: if connected, iterate the node-map loaded in constructor and populate the property-map, connect QOpcUaNode::dataChangeOccured to myClass::nodeValueUpdate (as in first post), subscribe to data changes on opcua server
- myClass::nodeValueUpdate as shown in first post.
Example from QML:
Tank { id: tank1 69 name: opcMap.tank1Title 78 volumeMaxValue: opcMap.tank1MaxVol 79 heightMaxValue: opcMap.tank1MaxHeight 80 volumeValue: opcMap.tank1Vol 81 heightValue: opcMap.tank1Height . topFieldEn: true . lowAlarmEn: opcMap.tank1MinAlarmEn highAlarmEn: opcMap.tank1MaxAlarmEn alarm: opcMap.tank1MinAlarm || opcMap.tank1MaxAlarm lowAlarm: opcMap.tank1MinAlarmLim highAlarm: opcMap.tank1HighAlarmLim relativeValue: opcMap.tank1RelVal }
Gives:
qrc:/Ballast.qml:88:13: Unable to assign [undefined] to double qrc:/Ballast.qml:87:13: Unable to assign [undefined] to double qrc:/Ballast.qml:86:13: Unable to assign [undefined] to double qrc:/Ballast.qml:85:13: Unable to assign [undefined] to bool qrc:/Ballast.qml:84:13: Unable to assign [undefined] to bool qrc:/Ballast.qml:83:13: Unable to assign [undefined] to bool qrc:/Ballast.qml:81:13: Unable to assign [undefined] to double qrc:/Ballast.qml:80:13: Unable to assign [undefined] to double qrc:/Ballast.qml:79:13: Unable to assign [undefined] to double qrc:/Ballast.qml:78:13: Unable to assign [undefined] to double qrc:/Ballast.qml:69:13: Unable to assign [undefined] to QString
As you can see, this is currently read only.
I tried adding just a simple qDebug() to print some random stuff inside the while-loop that's adding the nodes to the property map and the "Unable to assign" errors appears in the application output before my qDebug-print outs!
So I somehow must delay the creation of the QML-part untill after the property map has been created?
How can I do this? Perhaps I can create some sort of a splash screen to display "current status" and possible error messages.Bear with me, I'm a newbie to Qt...
-
QML code is initialized when you call
setSource
on QML engine. If you don't have your data ready then, there are several options:- first, make sure you register the QML type before you call
setSource
- initialize your map with zeroes or some empty values while you wait for real data
- or use Loader component to load your Tank objects only after your map is ready
- or use Binding element to only set values in QML if some condition is met
- first, make sure you register the QML type before you call