QML: How to Access non-trivial C++ member-objects? (eg. derived from QQuickPaintedItem).
-
I have two substantive classes each independently instantiated in QML. The first is the main QML Component found on a TabView tab, so there can be many. Further down the tab's tree structure, a button launches a child window whose QML file instantiates the second class. The problem is that the two are conceptually associated with each other but not implemented so. Information that should be directly passed from the first class to the second in C++ is being routed through the QML layer via signals and slots.
I want the first class
FooDevice.h
to own an object-instance of the secondFeatureComponent.h
as a class-member. In the QML Child-Window instead of instantiating a new C++/QML Feature object how can I reference the existing member object of the Device class?The current child-window is instantiating a
FeatureComponent
class derived fromQQuickPaintedItem
; this block defines visually where the image is to be displayed in addition to creating the object. I need the former without the later. How is this done? . . . (See two variations ofFeatureComponent.qml
below.)
Thank you,
PS. I've already researched the QT Documentation, forums, and DeveloperDays videos but not found an answer. A shortlist of items reviewed:
http://doc.qt.io/qt-5/qtqml-cppintegration-overview.html
http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html
http://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html
http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html
https://youtu.be/Vh7BxaYuszo QtWS17 QML For C++ Developers, Bo Thorsen
https://youtu.be/6vhIq3Nxmz0 QtDD14 -C++/QML Judgement Day - Bo Thorsen
https://forum.qt.io/topic/83392/access-model-owned-by-class-in-qml
Original QML that must be resolved.
// FeatureComponent.qml Window { GroupBox { Button { id: getImage_btn; text: qsTr("View") onClicked: { loadedDevice.getImage(param.x); // Sends Signal to FooDevice NOT a FeatureComponent object. } } } Rectangle { FeatureComponent { // PROBLEM: <<--- Instantiates new C++ Object here. id: displayImage // The image (implicitly?) displays in this box. anchors.fill: parent anchors.margins: 10 visible: true enabled: true // DESIGN PROBLEM HERE: // First: Receives signal from C++ DEVICE object: // "emit imageReceived(<const QByteArray&> imageData);" // Then: Relays entire image to independent C++ FeatureComponent object Connections { target: loadedDevice onImageRecevied: { // <<--- catch signal displayImage.processImage(imageData); // <<--- relay signal data.deleteLater(); // Illegal call occasionally invokes garbage-collection... } } } } }
Broader context with changed & failing FeatureComponent.qml
/** * Primary root-object. Most business-logic is here or in a member-objects. * All resources and sub-systems are owned/managed by the Device. */ class FooDevice : public DeviceBase { Q_OBJECT Q_PROPERTY (QString ... ) Q_PROPERTY (QString ... ) public: FooDevice(DeviceBase *parent = 0); ~FooDevice(); Q_INVOKABLE void ...(); Q_INVOKABLE void ...(); private: SocketWrapper m_socket FeatureComponent m_feature1; // <--- FeatureComponent m_feature2; // <--- // 500 more lines ... } /** * FeatureComponent is a non-trivial module previously instantiated in QML, * independent of FooDevice. From a C++ perspective, it's clear FeatureComponents * should be class member-objects of Devices. */ class FeatureComponent : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY (int ... ) Q_PROPERTY (int ... ) public: explicit FeatureComponent(const SocketWrapper& m_socket, QQuickItem *parent = 0); ~FeatureComponent(); Q_INVOKABLE void ...(); Q_INVOKABLE void ...(); void paint(QPainter *painter) override; // 100 more lines ... private: const SocketWrapper& m_socket; // Reference to Invoker's socket-connection. (new) } // -- Begin QML -- // main.qml ApplicationWindow { id: mainWindow TabView { id: myDevices ... function loadTab( name ) { myDevices.addTab(name, Qt.createComponent("deviceTab.qml")) } } } // deviceTab.qml ColumnLayout { id: deviceTabInstance FooDevice { // <<--- Instantiates C++ Object here. id: deviceInstance ... } // ---- This portion is in another file; several levels deeper. property variant winFeature1: Window property variant winFeature2: Window RowLayout { Button { onClicked: { var component = Qt.createComponent("FeatureComponent.qml") winFeatureA = component.createObject(deviceTabInstance) winFeatureA.show() } } } } // FeatureComponent.qml Window { GroupBox { /* UI controls and basic logic. */ } Rectangle { FooDevice.m_feature1 { // FAILS: <<-- Need to reference & display existing FooDevice.m_feature1 id: displayImage // Not create a new one out of thin air. anchors.fill: parent visible: true ... // QQuickPaintedItem's Image is (implicitly) drawn here. } } }