Is it safe to bind to C++ subobject's property in QML?
-
C++:
database c++ object is exposed to QML as a context property.
database c++ object has a method getDbpointObject() that returns pointer to databasePoint C++ object.
databasePoint C++ object has a property named cppProp.main.cpp:
// expose database object to qml database databaseObj; engine.rootContext()->setContextProperty("database", (QObject*)&databaseObj); // register databasePoint class qmlRegisterType<databasePoint>("DBPoint", 1, 0, "DBPoint");
database.h:
databasePoint *database::getDbpointObject()
databasePoint.h:
Q_PROPERTY(QVariant cppProp READ cppProp WRITE setcppProp NOTIFY cppPropChanged)
QML:
qmlComp is a custom QML component.
qmlComp has a QML property named qmlCompProp.
On completion of qmlComp creation, databasePoint c++ object is assigned to qmlCompProp.qmlComp.qml:
Item { property var qmlCompProp: ({}) // qml property Component.onCompleted: { qmlCompProp = database.getDbpointObject() // qml property holds the databasePoint c++ object } }
Question:
In binding.qml, QML property bindProp is binded to myQmlComp.qmlCompProp.cppProp
Is this binding safe?
Will the binding always be resolved?
databasePoint c++ object is assigned to qmlCompProp in Component.onCompleted. Until then, qmlCompProp is an empty object. Will it have an impact on binding resolution?
Will the order of properties evaluation in binding.qml have an impact on binding resolution?binding.qml:
property int bindProp: myQmlComp.qmlCompProp.cppProp // is this binding safe? qmlComp{id: myQmlComp}
-
Response from Qt Support:
In binding.qml, QML property bindProp is binded to myQmlComp.qmlCompProp.cppProp Is this binding safe?
Looks like.Will the binding always be resolved?
Assuming no reference issues, yesdatabasePoint c++ object is assigned to qmlCompProp in Component.onCompleted. Until then, qmlCompProp is an empty object. Will it have an impact on binding resolution?
This case should work. However, the binding is initially made for the empty object in that case (depending on how this is all instantiated) and then after the onCompleted, it updates the binding to refer to that real cppProp (instead of dummy one it created to the empty object).Will the order of properties evaluation in binding.qml have an impact on binding resolution?
Not in this case at least. You could have some issue if you had other dependent properties for the binding, like if you had an array in between and its index was another property. -
It's safe as in it won't crash.
Before your
onCompleted
theproperty int bindProp: myQmlComp.qmlCompProp.cppProp
will give a warning about bindingundefined
toint
.You could bypass that by doing
property int bindProp: myQmlComp.qmlCompProp.cppProp ?? 0
//nullish coalescingBut why don't you do
property var qmlCompProp: database.getDbpointObject()
in yout qmlComp? -
@GrecKo said in Is it safe to bind to C++ subobject's property in QML?:
But why don't you do
property var qmlCompProp: database.getDbpointObject()
in yout qmlComp?prop1 and prop2 are passed to the database.getDbpointObject(prop1, prop2) function. prop1 and prop2 are properties of qmlComp. These properties are set when an instance of qmlComp is created.
Item { required property string prop1 property bool prop2: false property var qmlCompProp: ({}) Component.onCompleted: { qmlCompProp = database.getDbpointObject(prop1, prop2) } }
Since the properties evaluation order is undefined, and qmlCompProp depends on both prop1 and prop2 values, I've opted to initialize qmlCompProp with an empty object and assign the actual object in Component.onCompleted.
Is this the right/recommended way, or is there a better way to handle this?Thanks for the information about the warning and it's workaround.