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 second FeatureComponent.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 from QQuickPaintedItem; 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 of FeatureComponent.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.
            }
    
        }
    }
    


Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.