I want to create a rectangle with inner shadow in QML
, something similar with what Photoshop
does:
QML
has InnerShadow
but I’m unable to achieve this effect. The closest I got was this
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
}
}
which is an idea I got from this post. However this example only works if root
has a significantly bigger size than myRectangle
and I don’t want that. I need e.g. a 200x10
square in which shadow is uniformly spread across the edges of the rectangle. I tried all kinds of values for the InnerShadow
properties but I couldn’t get even close to the effect I want.
Can this be achieved using QML
?
3
Answers
The “correct” approach – quotation marks needed – to use the effect should be this one:
As you can see it is slightly different from the propose solution in the other question. Using this code you still need to left 2 pixels, to have the effect, which results in a white border (or whatever is the background color). The issue can be easily solved by changing the
root
to be aRectangle
.Final example solution follows. Clearly you can extract the
root
component (and related children) and place it in aComponent
or a different.qml
file for later usage.The resulting window for the final code example:
The InnerShadow element is like most of the Graphics Effects elements in QML a GLSL shader, and the way it find edges is by looking for a transition between transparent and non-transparent. If you apply the filter to a completely solid graphics element it wouldn’t find any edges, and therefore no shadows. This is exactly the same way the Photoshop filter works, it also finds the edge by scanning for edges from transparent to non-transparent (as in the example you supplied). It could have treated the edges of the graphics area as implicit edges, but that would limit is usability considerably. Here’s the source for for InnerShadow. Which again uses FastInnerShadow or GaussianInnerShadow depending on the fast attribute.
If you want an implementation that you can just add on to existing elements without having to care about having transitions between transparent and non-transparent edges you could use this:
Here was my solution
GoodInnerShadow.qml
Sample Usage
Result