PDA

View Full Version : setClipPath on child widgets.



bunjee
24th May 2007, 11:44
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.

bunjee
26th May 2007, 16:36
:crying:

Ben.

marcel
26th May 2007, 16:43
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.

marcel
27th May 2007, 12:46
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

bunjee
27th May 2007, 16:37
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 ?

marcel
27th May 2007, 18:38
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

marcel
27th May 2007, 19:30
You can use QPolygonF::toPolygon to get a polygon with int coordinates.
This should be fit to pass to a QRegion constructor.

Regards

bunjee
27th May 2007, 19:34
Great it seems to be working :


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.

marcel
27th May 2007, 19:39
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

marcel
27th May 2007, 20:12
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