While Qt provides the QGraphicsDropShadowEffect, there's no "Neumorphism" effect available:
In css there is the box-shadow
property (that's how it's done in the image above), which can have multiple colors, but Qt lacks support for that property, and it's not possible to apply more than one graphics effect at once.
Can this be done?
The solution is to create a custom subclass of QGraphicsEffect and using gradients.
At first I thought about following the same concept used for CSS, subclassing QGraphicsDropShadowEffect and using another one internally to draw the "other" shadow, but I didn't like the result: in certain situations (usually when radius and contrast are too big) it just doesn't work:
If you look closely, you'll find out that the result is too similar to the drop shadow, like the object is floating, while it should be "extruding".
The only effective solution I found was to manually draw everything, using linear gradients for borders and composite gradients for the corners. While the first is pretty logical, the second required a bit of ingenuity by using composite modes of QPainter: Qt only has radials and conical gradients, but there is no "mix" between them.
The trick then was to create a radial gradient for the "light" color with the full color at the center and the same color at the border with 0 alpha, then superimpose a conical gradient for the "dark" color (with the "dark" color on start and the "light" at 90°), which will be painted using the alpha component of the first gradient.
Then it's just a matter of creating functions to update each one of the properties: distance (the extent of the effect), color (used for the gradients, defaults to the application's QPalette.Window color role), origin (the corner used as the "source" for the light) and an optional clipRadius for rounded borders.
Some important notes:
length
property;clipRadius
property allows rounded border clipping, but it's not perfect, since QPainter's clipping doesn't support antialiasing; I'll see if I can address this issue in the future;And here is a comparison between the Qt QGraphicsDropShadowEffect, the css emulation, and my NeumorphismEffect (the last two have rounded borders: the css version uses the
border-radius
property while mine is set withclipRadius
):