comp1201
comp1201

Reputation: 415

QML layer element "reveals" element above it when they overlap

Is it possible in QML, maybe using shader effects with layers, to create an item that makes another item (with a higher z index) visible only when the two layers overlap? I've been messing aroud with OpacityMask and ThresholdMask but have been unable to figure it out. The effect I'm looking for in the context of the example below would be if the the black circle was only visible when the two red squares are under it:

current:

enter image description here

desired:

enter image description here

Some key points are that the bottom layer (red squares) must be moveable (OpacityMask doesn't seem to let you drag the maskSource) and the bottom layer needs to also be able to contain other elements within it that the black circle responds to. Any guidance towards the right things to learn in order to achieve this would be appreciated. Here is the QML for the red squares and black circle thing. The red squares are draggable as one element:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12

Window {
    id: main_window
    visible: true
    width: 1500
    height: 1000
    title: qsTr("Hello World")

    Item {
        width: main_window.width
        height: main_window.height
        LinearGradient {
            anchors.fill: parent
            start: Qt.point(0, 0)
            end: Qt.point(main_window.width, 0)
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#003cff" }
                GradientStop { position: 1.0; color: "#9afff9" }
            }
        }
    }

    Rectangle {
        id: sfg
        width: 175
        height: 75
        color: 'transparent'
        RowLayout {
            width: parent.width
            height: parent.height
            spacing: 25

            Rectangle {
                Layout.preferredWidth: 75
                Layout.fillWidth: false
                Layout.fillHeight: true
                color: 'red'
            }

            Rectangle {
                Layout.preferredWidth: 75
                Layout.fillWidth: false
                Layout.fillHeight: true
                color: 'red'
            }

        }
        MouseArea {
            cursorShape: Qt.PointingHandCursor
            anchors.fill: parent
            drag {
                target: sfg
            }
        }
    }

    Rectangle {
        id: mask
        color: 'black'
        x: 400
        y: 200
        width: 100
        height: 100
        visible: true
        opacity: 1
        radius: 50
    }
}

Upvotes: 3

Views: 1763

Answers (1)

Albertino80
Albertino80

Reputation: 1093

Like this?

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.12

Window {
    id: main_window
    visible: true
    width: 1500
    height: 1000
    title: qsTr("Hello World")

    Item {
        width: main_window.width
        height: main_window.height
        LinearGradient {
            anchors.fill: parent
            start: Qt.point(0, 0)
            end: Qt.point(main_window.width, 0)
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#003cff" }
                GradientStop { position: 1.0; color: "#9afff9" }
            }
        }
    }

    Rectangle {
        id: sgfBox
        anchors.fill: parent
        color: "transparent"

        Rectangle {
            id: sfg
            width: 175
            height: 75
            color: 'transparent'
            RowLayout {
                width: parent.width
                height: parent.height
                spacing: 25

                Rectangle {
                    Layout.preferredWidth: 75
                    Layout.fillWidth: false
                    Layout.fillHeight: true
                    color: 'red'
                }

                Rectangle {
                    Layout.preferredWidth: 75
                    Layout.fillWidth: false
                    Layout.fillHeight: true
                    color: 'red'
                }

            }
            MouseArea {
                cursorShape: Qt.PointingHandCursor
                anchors.fill: parent
                drag {
                    target: sfg
                }
            }
        }
    }

    Rectangle {
        id: mask
        anchors.fill: parent
        color: "transparent"

        Rectangle {
            color: 'black'
            x: 400
            y: 200
            width: 100
            height: 100
            opacity: 1
            radius: 50
        }

        layer.enabled: true
        layer.effect: OpacityMask {
            maskSource: sgfBox
        }
    }
}

Upvotes: 3

Related Questions