0

I'm attempting to add a drop shadow effect around a QML popup, but when I do this with a MultiEffect, it creates an additional border around the popup (beyond the shadow).

Here's a minimal QML example that shows the problem I'm encountering:

import QtQuick
import QtQuick.Controls
import QtQuick.Effects

ApplicationWindow {
    width: 500
    height: 400
    visible: true

    color: "#E0E0E0"

    Button {
        text: "Open Popup"
        anchors.centerIn: parent
        onClicked: popup.open()
    }

    Popup {
        id: popup
        modal: true
        focus: true
        x: (parent.width - width) / 2
        y: (parent.height - height) / 2
        width: 200
        height: 150

        background: Rectangle {
            id: bg
            anchors.fill: parent.item
            color: "white"
            radius: 10
        }

        MultiEffect {
            anchors.fill: parent
            source: bg
            shadowEnabled: true
            shadowHorizontalOffset: 5
            shadowVerticalOffset: 5
        }

        Column {
            anchors.centerIn: parent
            spacing: 10

            Text { text: "This is a popup" }
            Button { text: "Close"; onClicked: popup.close() }
        }
    }
}

106c8606-3132-4a77-b395-3c0c16399637-image.png

In the past, I have used RectangularGlow with great success. This item was much easier to work with. For example:

background: Rectangle {
        anchors.fill: parent
        border.width: 1
        border.color: "black"
        color: root.color

        RectangularGlow {
            z: -1
            anchors.fill: parent
            glowRadius: 12
            spread: 0.1
            color: Colors.black
            opacity: 0.6
        }
}

This works much better. However, unfortunately import Qt5Compat.GraphicalEffects is not available to me on this new project because I am using PyQt6, and Qt5Compat is not available with PyQt6, so I'm forced to resort to MultiEffect that has this strange border.

I'm not attached to using MultiEffect, so if there's a different way to achieve a dropshadow effect (that is compatible with PyQt6) I'd be happy to use that instead, but MultiEffect is the closest thing I've gotten to achieving this effect.

1 Answer 1

2

There is no "additional border" here.
The effect is caused by the background and its shadow, which is rendered inside the background's bounds (not outside it).
You only need to move the MultiEffect inside the background component, as in the following example:

Popup {
    width: 200; height: 150
    anchors.centerIn: parent
    modal: true
    visible: true

    background: Rectangle {
        radius: 10
        layer.enabled: true
        layer.effect: MultiEffect {
            anchors.fill: parent
            shadowEnabled: true
        }
    }

    Text { 
        anchors.centerIn: parent
        text: "This is a popup"
    }
}

However, I recommend against using MultiEffect for rectangular shapes. Instead, use RectangularGlow or RectangularShadow.
MultiEffect has a more complex implementation (it uses blur) and is designed for non-rectangular shapes (e.g., transparent PNG or WebP files).
In contrast, RectangularShadow uses a simple SDF formula, which is significantly faster.

Example using RectangularShadow:

Popup {
    // ...

    background: Item {
        RectangularShadow {
            anchors.fill: rect
            radius: rect.radius
            blur: 30; spread: 10
            color: "#55000000"
        }

        Rectangle {
            id: rect
            anchors.fill: parent
            radius: 10
        }
    }

    // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, this was exactly what I needed! I figured that the problem had to do with drawing the shadow inside the bounds of, but when I tried moving the MultiEffect inside of the background, I did it as a child rather than using layer.effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.