Solved Insert QML objects from C++ without QQmlApplicationEngine
-
Hello,
I have two questions, a concrete one and a more general one about my approach.
I'll start with the setting, as it is now.
I need to create a custom QML component dynamically. This component is stored in a QML file on disk and I already managed loading it using a
Loader
. This components gets data from C++ objects. I instantiate those objects before loading and announce them to the engine using context properties. This approach is still static though and I want to be able to load an unknown number of this qml object. I briefly looked at the QML dynamic scene example, but I am unsure how fitting this example is for my scenario. The Scene should not change on a button click (which would be purely QML), but as soon as a serial device is attached (which is C++ with signals). Also, the QML objects have C++ properties and the example does not deal with this.Another problem that comes to mind is that I need multiple instantiations of the custom component. Setting the C++ objects using context properties would not be unambigious anymore. So, I found the following approach ( see the answer of that question ): https://stackoverflow.com/questions/23613936/c-qml-how-to-define-and-handle-multiple-contexts-for-dynamically-created-comp . Based on that, my current approach looks like this:
/** get "anchor" points */ QQmlEngine* engine = ...; QQmlContext* rootContext = engine->rootContext(); QQmlContext* childContext = new QQmlContext(rootContext); QObject *rootGrid = engine->rootContext()->findChild<QObject*>("rootGrid"); /** Set up controllers */ A* obj = new A; childContext->setContextProperty("control", obj); QQmlComponent comp(engine, QUrl("qrc:/mycomponent.qml")); QQuickItem* compInstance = qobject_cast<QQuickItem*>(comp.create(childContext)); compInstance->setParent(rootGrid);
I want to place the new component in the component rootGrid which is a
GridLayout
.Now the problem is that rootGrid is a
nullptr
. I found that root objects can also be obtained from a QQmlApplicationEngine, but I cannot use anything else but a QQmlEngine. So: How can I get a root item instead? I do not believe I can create the QML objects from QML itself, due to the context properties that I also cannot avoid.Secondly, am I taking the correct approach? Basically, my situation is as follows.
I have n data sources. I don't know n and n can change during execution. There is an interface class A that accepts a data source and manages the graphical representation in the QML object (a controller, that I currently set by a context property). This class also needs some instantiation, creating it is not enough. During instantiation, it connect to several other classes that also need to be created. Class B emits a signal as soon as I need a new instance of my custom control on the UI. Due to the complexity on the C++ side, I chose to handle it in C++ - but maybe, it is actually easier to do in QML?
-
Hello,
with the help of @KillerSmath (thank you so much :D), I managed to solve the problem.
Apparently, I cannot get the root item using the QQmlEngine but I was able to get a root item from the QQuickWindow. I hope this information might be useful for others, so I will not delete the question.