How do I implement a Rectangle in QML with an inner shadow?
See example in link below:
Create inner shadow in UIView
UPDATE:
Here's a simplified version of what I'm trying to do (which does not show any shadow):
import QtQuick 2.0
import QtGraphicalEffects 1.0
Item {
width: 400
height: 400
Item {
anchors.fill: parent
Rectangle {
id: myRectangle
anchors.centerIn: parent
width: 200
height: 200
color: "grey"
}
}
InnerShadow {
anchors.fill: myRectangle
cached: true
visible: true
horizontalOffset: 0
verticalOffset: 0
radius: 25
samples: 16
color: "#b0000000"
smooth: true
source: myRectangle
}
}
I'm sorry. My stupid... I got it wrong when i simplified the code (the Item was used for a DropShadow test, which works).
This is how it was supposed to look like:
import QtQuick 2.0
import QtGraphicalEffects 1.0
Item {
width: 400
height: 400
Rectangle {
id: myRectangle
anchors.centerIn: parent
width: 200
height: 200
color: "grey"
}
InnerShadow {
anchors.fill: myRectangle
cached: true
visible: true
horizontalOffset: 0
verticalOffset: 0
radius: 25
samples: 16
color: "#b0000000"
smooth: true
source: myRectangle
}
}
I'm not sure why, but it works if you use the item above the item you're trying cast a shadow within (in this case it just happens to be the root item, but it doesn't have to be):
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
}
}
I got the idea from QTBUG-27213 when I was searching for related bugs.
Here https://bugreports.qt.io/browse/QTBUG-56467 in first comment is the informative answer for those issues:
(c) Gunnar Sletta:
The InnerShadow will produce a shade in the opaque areas based on the translucent areas of the source object. When the source is fully opaque (like in the case of this rectangle, the result will thus be no shading.
DropShadow has a transparentBorder property which is set to true by default to aid the user in getting the expected results even for fully opaque input. The InnerShadow lacks this.
On a side note, the InnerShadow also uses the "old" gaussian code which requires significantly more samples to get the right
Anyway, the way do get an inner shadow on a rectangle is to pad it with a single pixel border of transparent pixels. This is also why it will sometimes work to give the parent of the intended source item as source of the effect. (Please note that this doesn't work in general, and that the parent is in fact unsupported as source as many GPUs will fail when you do this).
The following code produces the expected results:
import QtQuick 2.4
import QtGraphicalEffects 1.0
Item
{
width: 320
height: 480
Item {
anchors.centerIn: parent
width: 100
height: 100
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: "lightsteelblue"
}
layer.enabled: true
layer.effect: InnerShadow {
color: "black"
samples: 32
radius: 10
spread: 0.4
}
}
}
Alternatively, if you want to save the extra item, and can live with a tiny bit of trickery:
Rectangle {
anchors.centerIn: parent
width: 100
height: 100
color: "lightsteelblue"
border.color: Qt.rgba(0, 0, 0, 0.01)
border.width: 1
layer.enabled: true
layer.effect: InnerShadow {
color: "black"
samples: 20
radius: 8.5
spread: 0.2
}
}
(the border.color, can't be 'transparent' because that is interpreted as no border)