Qt 半透明项目的DropShadow

Qt 半透明项目的DropShadow,qt,qml,qtquick2,Qt,Qml,Qtquick2,我在项目中创建阴影时遇到问题。项目不是完全不透明的,并且绘制的阴影显示在项目后面,从而降低透明度效果 我需要一些东西,如右图所示,但我通过尝试得到的东西显示在左边。我需要你透过这个物体看,因为背景不是实心的。 我试图使用maskEf,但对象变得完全不透明。我设法定义的最接近的解决方案是使用另一个形状相同但完全透明且具有solid edge的元素。但是我不喜欢solid edge,有什么建议吗 第一次尝试。这使得rec1中的opacity等于1: Rectangle { id: rec1

我在项目中创建阴影时遇到问题。项目不是完全不透明的,并且绘制的阴影显示在项目后面,从而降低透明度效果

我需要一些东西,如右图所示,但我通过尝试得到的东西显示在左边。我需要你透过这个物体看,因为背景不是实心的。

我试图使用
maskEf
,但对象变得完全不透明。我设法定义的最接近的解决方案是使用另一个形状相同但完全透明且具有solid edge的元素。但是我不喜欢solid edge,有什么建议吗

第一次尝试。这使得
rec1
中的
opacity
等于
1

Rectangle {
    id: rec1; color: "white"; opacity: 0.5
    anchors.fill: parent; radius: CalcSize.getW(8)
    layer.enabled: true
    layer.effect: DropShadow {
    id: shadowEf
        anchors.fill: rec1
        source: rec1
        horizontalOffset: 3
        verticalOffset: 3
        radius: 15
        samples: 16
        color: "red"
        transparentBorder: true
    }
}
第二次尝试。这将保持
rec1的
opacity
,但显示
sourceMaskEf的边框

DropShadow {
    id: shadowEf
    anchors.fill: sourceMaskEf
    source: sourceMaskEf
    horizontalOffset: 3
    verticalOffset: 3
    radius: 15
    samples: 16
    color: "red"
    transparentBorder: true
}

Rectangle {
    id: sourceMaskEf; color: "transparent"
    anchors.fill: rec1; radius: rec1.radius
    border { width: offset; color: "white"; }
}

OpacityMask {
    id: maskEf
    opacity: 1
    anchors.fill: rec1
    source: ShaderEffectSource {
            sourceItem: shadowEf
            hideSource: false
        }
    maskSource: ShaderEffectSource {
            sourceItem: sourceMaskEf
            hideSource: false // if set true the shadow is hide to
        }
    cached: true
}

Rectangle {
    id: rec1; color: "white"; opacity: 0.5
    anchors.fill: parent; radius: CalcSize.getW(8)
}
编辑 在巴卡罗佐的建议下,这是我的解决方案。它更接近我想要的:

Component {
    id: fondoItemPromo
    Item {
        id: item1; opacity: 0.5
        layer.enabled: true; anchors.fill: parent
        anchors.margins: CalcSize.getW(5) //Just for test
        Rectangle {
            id: rec1; color: "white"
            anchors.fill: parent; radius: CalcSize.getW(8)
            Item {
                id: item2; opacity: 0.5; layer.enabled: true
                anchors.fill: parent; clip: true
                Rectangle {
                    id: rec2; color: "white"
                    anchors.fill: parent; radius: CalcSize.getW(8)
                    layer.enabled: true
                }
                DropShadow {
                    anchors.fill: rec2
                    source: rec2
                    transparentBorder: true
                    horizontalOffset: 3
                    verticalOffset: 3
                    radius: 15
                    samples: 16
                    color: "black"; clip: true
                }
            }
        }
    }
}
但是,阴影不会延伸到元素的限制之外,如在拐角处所示:


有什么建议吗

假设阴影应该是半透明的-否则整体效果会非常难看-您可以使用以下方法解决此问题:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls.Styles 1.3

ApplicationWindow {
    width: 200
    height: 300
    visible: true
    color: "steelblue"
    
    Item {
        id: layered
        opacity: 0.2
        layer.enabled: true
        anchors.fill: parent
        
        Rectangle {
            id: rec1
            width: 100
            height: 100
            anchors.centerIn: parent
            radius: 8
        }
        
        DropShadow {
            id: drop
            anchors.fill: rec1
            source: rec1
            horizontalOffset: 5
            verticalOffset: 5
            radius: 15
            samples: 16
            color: "red"
            transparentBorder: true
        }
    }
}
这是产生的
矩形
几乎不可见的背景色,并应用了正确的阴影:

编辑 该效果可以在不同级别上进行组合,如中所述

考虑到你的编辑,我认为你把这里的东西复杂化了一点。我上面给出的示例是一种显示不透明度应该按预期工作的方法。考虑到您所显示的错误,我决定提供一个通用的解决方案,您应该(希望)开箱即用

白色的
矩形
充当实际内容的容器。因此,应该在不同的QML文件中定义它。通过这种方式,我们可以提供一个属性,即定义在将子项添加到组件时,子项
应放置在何处。通过添加es,我们还可以微调组件、更改颜色、阴影方向和其他图形方面。组件的可能定义如下所示:

// ShadowedComponent.qml    

import QtQuick 2.0
import QtGraphicalEffects 1.0

Item {
    opacity: 0.5
    layer.enabled: true
    clip: true
    property alias color: rec.color
    property alias dropColor: drop.color
    property alias voff: drop.verticalOffset
    property alias hoff: drop.horizontalOffset
    property alias radius: rec.radius
    property alias dropRadius: drop.radius
    property alias samples: drop.samples
    default property alias childrenz: rec.children //(1)

    property int margins: 20   //(2)

    Rectangle {
        id: rec
        width: 100
        height: 100
        anchors.fill: parent
        anchors.margins: margins
        radius: 8
        clip: true
    }

    DropShadow {
        id: drop
        anchors.fill: rec
        source: rec
        horizontalOffset: 5
        verticalOffset: 5
        radius: 15
        samples: 16
        color: "darkgray"
        transparentBorder: true
    }
}
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1

ApplicationWindow {
    width: 300
    height: 600
    visible: true

    Rectangle {
        anchors.fill: parent
        gradient:  Gradient {
            GradientStop { position: 0.0; color: "cyan" }
            GradientStop { position: 0.5; color: "#0099FF" }
            GradientStop { position: 1.0; color: "#6699FF" }
        }

        ColumnLayout {
            anchors.fill: parent
            anchors.margins: 10

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true
                voff: -5
                hoff: -10

                Image {
                    source: "http://avatarmaker.net/free-avatars/avatars/animals_216/cats_237/kitty_close_up_avatar_100x100_36619.jpg"
                    anchors.fill: parent
                    anchors.margins: 3
                }
            }

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true

                dropColor: "red"
                opacity: 0.7

                Text {
                    anchors.centerIn: parent
                    text: qsTr("QML ROCKS!!!")
                }
            }

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true
                voff: -5
                hoff: -10

                dropColor: "red"

                BusyIndicator {
                    anchors.centerIn: parent
                    running: true
                }
            }

            ShadowedComponent {
                 Layout.fillHeight: true
                 Layout.fillWidth: true
                 opacity: 0.6


                 Test {
                    anchors.fill: parent
                    opacity: 1
                    margins: 10

                    Text {
                        anchors.centerIn: parent
                        text: qsTr("QML ROCKS!!!")
                    }
                }
            }
        }
    }
}
(1)中的声明是至关重要的,正如前面的文本所暗示的:我们指定
ShadowedComponent
的任何子级都是内部
矩形的自动子级(以所需的对齐方式-见下文)。(2)中的属性
边距
也很重要:它为阴影的正确显示提供了必要的间隙。等于零的值会导致出现错误,因为阴影不能超过项目的边界

该组件可按如下方式使用:

ShadowedComponent {
    color: "red"
    dropColor: "black"
    voff: 3
    hoff: 3
    radius: 8
    dropRadius: 8
    samples: 16

    // inner content...
}
ShadowedComponent {

    // inner content...
}
或者,由于所有属性都有一个默认值,如下所示:

ShadowedComponent {
    color: "red"
    dropColor: "black"
    voff: 3
    hoff: 3
    radius: 8
    dropRadius: 8
    samples: 16

    // inner content...
}
ShadowedComponent {

    // inner content...
}
最后,可能的用法示例如下:

// ShadowedComponent.qml    

import QtQuick 2.0
import QtGraphicalEffects 1.0

Item {
    opacity: 0.5
    layer.enabled: true
    clip: true
    property alias color: rec.color
    property alias dropColor: drop.color
    property alias voff: drop.verticalOffset
    property alias hoff: drop.horizontalOffset
    property alias radius: rec.radius
    property alias dropRadius: drop.radius
    property alias samples: drop.samples
    default property alias childrenz: rec.children //(1)

    property int margins: 20   //(2)

    Rectangle {
        id: rec
        width: 100
        height: 100
        anchors.fill: parent
        anchors.margins: margins
        radius: 8
        clip: true
    }

    DropShadow {
        id: drop
        anchors.fill: rec
        source: rec
        horizontalOffset: 5
        verticalOffset: 5
        radius: 15
        samples: 16
        color: "darkgray"
        transparentBorder: true
    }
}
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1

ApplicationWindow {
    width: 300
    height: 600
    visible: true

    Rectangle {
        anchors.fill: parent
        gradient:  Gradient {
            GradientStop { position: 0.0; color: "cyan" }
            GradientStop { position: 0.5; color: "#0099FF" }
            GradientStop { position: 1.0; color: "#6699FF" }
        }

        ColumnLayout {
            anchors.fill: parent
            anchors.margins: 10

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true
                voff: -5
                hoff: -10

                Image {
                    source: "http://avatarmaker.net/free-avatars/avatars/animals_216/cats_237/kitty_close_up_avatar_100x100_36619.jpg"
                    anchors.fill: parent
                    anchors.margins: 3
                }
            }

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true

                dropColor: "red"
                opacity: 0.7

                Text {
                    anchors.centerIn: parent
                    text: qsTr("QML ROCKS!!!")
                }
            }

            ShadowedComponent {
                Layout.fillHeight: true
                Layout.fillWidth: true
                voff: -5
                hoff: -10

                dropColor: "red"

                BusyIndicator {
                    anchors.centerIn: parent
                    running: true
                }
            }

            ShadowedComponent {
                 Layout.fillHeight: true
                 Layout.fillWidth: true
                 opacity: 0.6


                 Test {
                    anchors.fill: parent
                    opacity: 1
                    margins: 10

                    Text {
                        anchors.centerIn: parent
                        text: qsTr("QML ROCKS!!!")
                    }
                }
            }
        }
    }
}
使用在不同文件中定义的组件,您可以通过
default
属性以声明方式将其与任何其他(自定义)组件组合。我们示例的总体结果如下所示。请注意,由于我们定义和使用了大量的
alias
es,每个组件的整体外观都是独一无二的。还要注意的是,组件可以自行组成(通过仔细调整给定阴影参数的裕度w.r.t):


嗯,我是不是遗漏了什么?我的图片中的
矩形
不是实心的,它是白色的,但因为它不是实心的,所以你可以看穿它(这就是为什么它的颜色“混合”了)背景。红色阴影不影响白色透明度,但它仍然存在,在
矩形
周围。感谢您的帮助,结果与我所看到的非常相似,但即使是我也有一个小问题,因为阴影没有绘制在元素边界之外,无法用“剪辑:对"工作非常棒,你上一个解决方案给我的和我想要的完全一样,唯一的问题是对象
ShadowedComponent
比父元素小得多,但这是使用负边距解决的,工作起来很有魅力,非常感谢,你是best@FabianMenco这是您可以使用
页边距调整的内容de>,如果我明白你的意思。无论如何,我很高兴问题解决了。高兴QML编码!:)