Access C++ factory-created objects from QML
-
Hey there.
I'm developing an application with a C++ backend and a QML frontend and I'm having troubles.
So, what I want to do is the following:
- A factory class of some sort is exposed to QML using
setContextProperty
. - The objects the factory outputs controller classes for different hardware devices.
- Each device has a different set of controls, that I want to write as independent QML files.
- Then, I need to get this newly created controller, access some function of it to return the QML resource, and display it. I guess a
Loader
would work.
The question then is about how to make the QML file for a specific controller know about the controller object? In the QWidgets world what I do is just make a custom QWidget that has a pointer to the controller (and vice-versa, actually). But now I don't know how to do this in QML.
In fact, I'm not even sure this is the right architecture.
I'll leave here an image explaining what I want to do:
Thanks!
- A factory class of some sort is exposed to QML using
-
Maybe this is what you're looking for: https://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html
-
That should solve the question of "How can this QML be displayed?"
Other question: "How can QML call this object method?".
Answer: The QML code inside some_file.qml must refer to the object you exposed via setContextProperty for the specific radio. So, if you called setContextProperty() with an object name of "specificRadio", then in some_file.qml, you could have the following somewhere in a code block, assuming volume member has been exposed to QML via a setVolume() setter:specificRadio.setVolume(100)
You could also use models to bind to data of your radio class.
-
Do these objects output by the factory have a lifetime that needs to exceed the QML component used for the object's controls? If not, I would make the object a QML (not Quick) type, and have the component that displays the controls also instantiate the object.
Even if they do have lifetimes that don't match the UI portion, the controls can be thin wrappers around the objects that really implement the backend. In the example below RadioBackend and TapeBackend are QObject derived classes that export Q_INVOKABLE functions and properties for communication with the UI. Register them with one of the qmlRegister* functions, depending on the desired interface.
For example:
Radio.qml:
Rectangle { color: control.colorTheme RadioBackend { id: control } Row { Button { onClicked: control.doAction() } Button { onClicked: control.doOtherAction() } } }
TapeDeck.qml:
Rectangle { color: control.colorTheme TapeBackend { id: control } Button { onClicked: control.doTapeAction() } }
main.qml:
Loader { property MediaType mediaType source: mediaType === MediaType.Radio ? "file://Radio.qml" : "file://TapeDeck.qml" }