Search code examples
qtqmlloader

How can I call a custom signal from a QML Component?


Is there a way to call a signal from a mouseArea included in a component which is loaded somewhere else?

onClicked in the example below is not entered when i click on the rectangle.

The structure needs to remain as defined. To be able to define a qml component that applies a shadow to any source

Here is the code:

Window{
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Item
    {
        id: mainRectangle
        anchors.centerIn: parent
        width: loaderId.width + 60
        height: loaderId.height + 60

        Rectangle {
            id: rect2
            anchors.right: mainRectangle.right
            anchors.top: mainRectangle.top
            anchors.rightMargin: -30
            anchors.topMargin: -30
            width: 100
            height: 100
            color: "red"
            opacity: 0.5
        }

        Loader {
            id: loaderId
            anchors.centerIn: parent
            sourceComponent: component
            active:true
        }
        visible: false
    }

    ShaderEffectSource {
        id: shader
        anchors.fill: mainRectangle
        anchors.margins: -30
        sourceItem: mainRectangle
        opacity: 0.5
        visible: true
    }

    Component {
        id: component
        Rectangle {
            id: rect
            width: 100
            height: 100
            color: "black"
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    console.log("Clicked!")
                    // call a signal from here
                }
            }
        }
    }
}

In the end the should show what it does now and the mouseArea should work.


Solution

  • onClicked in the example below is not entered when i click on the rectangle.

    mainRectangle is not visible, and items that aren't visible don't get input events. Since the MouseArea is a child of mainRectangle, it won't get events either.

    In the end the should show what it does now and the mouseArea should work.

    Instead of hiding the source item and using ShaderEffectSource, you can set the opacity directly on mainRectangle and use item layers (the link has a similar example) to ensure that there is no overlap due to transparency:

    import QtQuick 2.0
    import QtQuick.Window 2.0
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Item {
            id: mainRectangle
            anchors.centerIn: parent
            width: loaderId.width + 60
            height: loaderId.height + 60
            opacity: 0.5
            layer.enabled: true
    
            Rectangle {
                id: rect2
                anchors.right: mainRectangle.right
                anchors.top: mainRectangle.top
                anchors.rightMargin: -30
                anchors.topMargin: -30
                width: 100
                height: 100
                color: "red"
            }
    
            Loader {
                id: loaderId
                anchors.centerIn: parent
                sourceComponent: component
                active: true
            }
        }
    
        Component {
            id: component
            Rectangle {
                id: rect
                width: 100
                height: 100
                color: "black"
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        console.log("Clicked!")
                        // call a signal from here
                    }
                }
            }
        }
    }