Unable to create qml component with C++ property passed as parameter
-
Hello,
I have a C++ signal that passes a C++ object (type registered with QML), and is caught by a QML component.
This QML component,creates another QML component which must have this C++ object as a property.
However, I am unable to make it work :-(I have tried 2 different things which you can see in the code bellow (I am not showing the C++ as it is insubstancial for the moment)
So, what is the proper way to "connect" a QML component with an existing C++ object?
ApplicationWindow {
visible: true; width: 640; height: 480Component { // Test version 1: Does not work as the "text" property initialization generates an error id: myTabButton TabButton { property HPACDevice device id: button text: device.value.toString() // causes: "TypeError: Cannot read property 'value' of null" } } Component { // Test version 2: Does "work", but does not do what I want as I end up with 2 instances of HPACDevice id: myTabButton2 TabButton { HPACDevice { id: device } id: button text: device.value.toString() // works, but I end up with 2 HPACDevice being instanciated! } } HPACgroup { id: group onNewDevice: { // respond to: void HPACgroup::newDevice(HPACDevice &device); myTabButton.createObject(row, {"device": device}); // test 1. Causes error myTabButton2.createObject(row, {"device": device}); // test 2: cause 2 instances of HPACDevice } } Column { id: row Button { // Just a button that tells the C++ group to add a device. In "real life", the devices will be created in reaction to OS events (USB Plugged detected in C++) width: 100; height: 100; text: "add" onClicked: group.addDevice() // Causes the C++ group create another "device". } }}
Thanks,
Cyrille -
Here is how you create a C++ object and then use it in QML.
You don't need to register the object either.
#pragma once #include <QObject> class Foo : public QObject { Q_OBJECT public: explicit Foo(QObject *parent = nullptr) : QObject(parent) { } Q_INVOKABLE QString hello() { return "hello world"; } };#include <QQmlApplicationEngine> #include <QQmlComponent> #include "foo.h" int main(int ac, char **av) { QApplication app(ac, av); // load qml engine and component auto eng = new QQmlApplicationEngine(); auto comp = new QQmlComponent(eng, QUrl("qrc:///qml/main.qml")); auto obj = comp->create(); if (!obj) return; // No registration required for this ... auto foo = new Foo(); eng->rootContext()->setContextProperty("foo", foo); return app.exec(); }And here is the QML:
import QtQuick 2.11 import com.ambershark.example.foo 1.0 Rectangle { width: 300 height: 300 Text { text: qsTr("Click me") anchors.centerIn: parent MouseArea { anchors.fill: parent onClicked: { console.log(foo.hello()) } } } -
Here is how you create a C++ object and then use it in QML.
You don't need to register the object either.
#pragma once #include <QObject> class Foo : public QObject { Q_OBJECT public: explicit Foo(QObject *parent = nullptr) : QObject(parent) { } Q_INVOKABLE QString hello() { return "hello world"; } };#include <QQmlApplicationEngine> #include <QQmlComponent> #include "foo.h" int main(int ac, char **av) { QApplication app(ac, av); // load qml engine and component auto eng = new QQmlApplicationEngine(); auto comp = new QQmlComponent(eng, QUrl("qrc:///qml/main.qml")); auto obj = comp->create(); if (!obj) return; // No registration required for this ... auto foo = new Foo(); eng->rootContext()->setContextProperty("foo", foo); return app.exec(); }And here is the QML:
import QtQuick 2.11 import com.ambershark.example.foo 1.0 Rectangle { width: 300 height: 300 Text { text: qsTr("Click me") anchors.centerIn: parent MouseArea { anchors.fill: parent onClicked: { console.log(foo.hello()) } } }Hello,
Thanks, this is actually valuable information as I was trying to do something similar!
However, it does not what I was trying to achieve here.
What I was trying to achieve was the creation of a QML object in response to the creation of a C++ object, with said C++ object being a "typed property" of the QML object, not a global variable (of course, multiple such objects will be instantiated)One of the reason why I would like it to be a registered property is so that, in QML, I get dynamic completion and other development niceties.
Cyrille