I find myself in a pickle trying to dynamically instantiate custom QML elements from C++.
So, to layout the problem:
- I have a light-weight
Nodeobject data structure that is abstracted from any UI. - Because of the memory heavy
QObjectand derived, I must instantiate the UI elements on demand. - Each
Nodehas a_ui*member, and eachUIhas a_node*member. - Each
Nodehas a unique_id, eachUIhas anIDPROPERTY, delivered from the_node*. The ID property is read only, since the ID is set uponNodeinstantiation and should not be modifiable. - QML elements must only have constructors with default parameters, e.g. cannot pass anything to the constructor.
- When the QML element is created, the
_node*member isNULL, so any QML child element ofUItrying to access the ID property cannot, because the_node*is not set upon instantiation, it can only be set by an aux method, but since the property is effectively a read-only constant, it is not updated anymore after the instantiation when the_node*member of theUIis actually set.
So basically, I need to be able to set the link to the corresponding Node of each UI upon creation, so that it is accessible to the UI QML elements, but I cannot pass it to a constructor, and since the property is read-only it is read only once, upon the UI instantiation, when the _node* UI member is still NULL, so the ID value cannot be accessed.
One quick and dirty solution that comes to mind is to add a NOTIFY idChanged() signal to emit when setting the _node* member post-instantiation even though the ID property never really changes, cannot and should not, and add a check for the ID getter - return a fake dummy arbitrary value if _node* is NULL, otherwise fetch the ID value from the _node* member. Needless to say, this is not elegant, and adds some overhead and the dummy ID value is a potential can of worms, so any ideas how to defeat the ill design of QML internals are welcome.
I just came with a solution, and a rather simple one. Considering that QtQuick is designed in a way that does not allow to specify constructor parameters and considering that the "create and set" approach has huge implications in my particular usage scenario, I decided to simply make the value available to/in the
UIconstructor even if not passed there as a parameter.So, instead of "create and set" I just do a "set and create" and use a static class member that is set before creating each item and used in the item constructor to set the data in time.
and the actual object creation:
Also, another method, which is applicable when you don't need the object set as early as in the constructor is to create the
QQmlComponentsbeginCreate(), set the needed properties, and finalize withcompleteCreate()