setClipPath on child widgets.
Hello I'm using "setClipPath" to specify a rounded clipped area in a parent widget.
Unfortunately that clipped rounded rectangle isn't taken into account in the child widgets : the painting event is overlapping it.
Any way to sort this out ?
Thanks.
Ben.
Re: setClipPath on child widgets.
Re: setClipPath on child widgets.
It should affect the children also.
Are you sure that when you created the children you passed the masked widget as parent? Or at leas a child of the masked widget.
Re: setClipPath on child widgets.
Sorry, I was under the impression that you were talking about QWidget::setMask. This applies on the children.
With QPainter::setClipPath it is a bit trickier if you want it to affect the children also.
Solution 1.
Reimplement paint event in the child widgets and compute the intersection of widget geometry rect with the parent's mask. Then call setClipPath in the child's paint event using the resulted intersection.
Solution 2.
As above, compute the intersection. But instead of overriding paintEvent in all the children use QWidget::setMask in the children with the intersection you computed.
This way you can use normal widgets as children and don't have to subclass all the widgets you use, as in the first case.
Solution 3.
Use QWidget::setMask. You set the mask only once, in the parent widget.
This will apply to any subsequent painting you will do and also on the children. :)
EDIT:
For intersection and other simple contour operations you should use QRegion.
Regards
Re: setClipPath on child widgets.
Solution 3.
Use QWidget::setMask. You set the mask only once, in the parent widget.
This will apply to any subsequent painting you will do and also on the children.
that's the solution I'd like to use, unfortunately setMask is expecting a QRegion, and my clipped area is a custom rounded rectangle path.
Any way to create a QRegion from a QPainterPath ?
Re: setClipPath on child widgets.
Try using QPainterPath::toFillPolygon() - call it with the default parameter - an identity matrix.
For a rounded rectangle it should return exactly what you need.
Then pass this QPolygonF to a QRegion.
Please note that it could not look like we expect, due to the float to int conversion.
I'm not sure yet though.
Regards
Re: setClipPath on child widgets.
You can use QPolygonF::toPolygon to get a polygon with int coordinates.
This should be fit to pass to a QRegion constructor.
Regards
Re: setClipPath on child widgets.
Great it seems to be working :
Code:
setMask
(QRegion(zePainter.
DrawRoundRect(QRect(rect
().
x() + 2, rect
().
y() + 2,
rect().width() - 4, rect().height() - 4),
2000 / rect().width(), 2000 / rect().height()).toFillPolygon().toPolygon()));
Thank you.
Unfortunately it's a bit pixelated, Any way to apply antialiasing or a float conversion ?
Ben.
Re: setClipPath on child widgets.
Quote:
Unfortunately it's a bit pixelated, Any way to apply antialiasing or a float conversion ?
Unfortunately you can't do anything about antialiasing when using masks.
The float conversion can be simplified as I have shown you in my previous post.
EDIT - I see now you already did that ( you used toPolygon ) .
So there isn't much you can do about that either.
Regards
Re: setClipPath on child widgets.
Is this masked widget the main widget of your app?
If not, and if you have a normal main window, then you could use transparent png's( for example a png that contains a nice, antialiased rounded rectangle), already antialiased, instead of clippings.
This way you can solve the antialiasing problem.
The problem is that you cannot use transparent images on top level windows, unless your window manager supports desktop compositions.
Currently only Vista with Aero enabled, Mac Os X, and X11 with the composite extension support it.
Regards