QML内阴影效果

时间:2015-04-08 14:29:44

标签: c++ qt qml qt-quick qtquick2

我想在QML中创建一个内部阴影的矩形,类似于Photoshop的内容:

enter image description here

QMLInnerShadow,但我无法达到此效果。我得到的最接近的是

import QtQuick 2.0
import QtGraphicalEffects 1.0

Item {
    id: root
    width: 300
    height: 300

    Rectangle {
        id: myRectangle
        anchors.centerIn: parent
        width: 100
        height: 100
        color: "grey"
    }

    InnerShadow {
        anchors.fill: root
        cached: true
        horizontalOffset: 0
        verticalOffset: 0
        radius: 16
        samples: 32
        color: "#b0000000"
        smooth: true
        source: root
    }
}

这是我从this帖子中得到的一个想法。但是,此示例仅在root的大小明显大于myRectangle并且我不希望这样的情况下才有效。我需要例如一个200x10正方形,其中阴影均匀分布在矩形的边缘。我为InnerShadow属性尝试了各种值,但我无法接近我想要的效果。

可以使用QML来实现吗?

2 个答案:

答案 0 :(得分:2)

使用效果的“正确”方法 - 所需的引号应该是这样的:

import QtQuick 2.0
import QtGraphicalEffects 1.0

Item {
   id: root
   width: 300
   height: 300

   Item {
       id: src
       anchors.fill: parent

       Rectangle {
           id: myRectangle
           anchors.centerIn: parent
           width: 100
           height: 100
           color: "grey"
       }
   }

   InnerShadow {
       anchors.fill: src
       cached: true
       horizontalOffset: 0
       verticalOffset: 0
       radius: 16
       samples: 32
       color: "#b0000000"
       smooth: true
       source: src
   }
}

正如您所看到的,它与另一个问题中的建议解决方案略有不同。使用此代码,您仍然需要留下2个像素才能产生效果,从而产生白色边框(或任何背景颜色)。将root更改为Rectangle

可以轻松解决该问题

最后的示例解决方案如下。显然,您可以提取root组件(及相关子组件)并将其放在Component或其他.qml文件中以供日后使用。

import QtQuick 2.4
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0

Window {
    width: 200
    height: 20
    visible: true

    Rectangle {     // was Item
        id: root
        anchors.fill: parent
        color: "grey"


        Item {
            id: src
            anchors.fill: parent

            Rectangle {
                id: myRectangle
                anchors.centerIn: parent
                width: root.width - 2
                height: root.height - 2
                color: "lightgrey"
            }
        }

        InnerShadow {
            anchors.fill: src
            cached: true
            horizontalOffset: 0
            verticalOffset: 0
            radius: 16
            samples: 32
            color: "#b0000000"
            smooth: true
            source: src
        }
    }
}

最终代码示例的结果窗口:

enter image description here

答案 1 :(得分:1)

InnerShadow元素就像QML中的大多数图形效果元素一样,GLSL着色器,它找到边缘的方式是寻找透明和非透明之间的过渡。如果将滤镜应用于完全实心的图形元素,则无法找到任何边缘,因此不会出现阴影。这与Photoshop滤镜的工作方式完全相同,它还通过扫描从透明到非透明的边缘来查找边缘(如您提供的示例中所示)。它可以将图形区域的边缘视为隐式边缘,但这将极大地限制可用性。这是InnerShadow的来源。根据快速属性,它再次使用FastInnerShadowGaussianInnerShadow

如果您想要一个可以添加到现有元素上的实现,而不必关心透明边缘和非透明边缘之间的过渡,您可以使用它:

Rectangle {
    id: myRectangle
    anchors.centerIn: parent
    width: 300
    height: 300
    color: "#AAAAAA"
}
Item {
    id: _innerShadow
    property var shadowSource: myRectangle
    property var color: "#B0000000"
    anchors.fill: shadowSource
    Item {
        id: _shadowMarker
        //width: source.width+1; height: source.height+1
        anchors.fill: parent;
        anchors.margins: -10
        ColorOverlay {
            anchors.fill: _shadowMarker;
            anchors.margins: 10
            source: _innerShadow.shadowSource
            color: "#00000000"
        }
        visible: false
    }
    InnerShadow {
        anchors.fill: _shadowMarker
        cached: true
        horizontalOffset: 0
        verticalOffset: 0
        radius: 16
        samples: 32
        color: _innerShadow.color
        smooth: true
        source: _shadowMarker
    }
}