If the shape you want to draw can be represented as a layering of other shapes, as with the image you've linked to, it's pretty easy to do:
First we need to build a QPainterPath
to represent the outer edge of the shape. We build it by layering up simpler shapes; in the case of your example we need a circle and a square. Note the use of QPainterPath::setFillRule(Qt::WindingFill)
: this will later affect the way that the path is painted (try removing it to see the difference!).
QPainterPath OuterPath;
OuterPath.setFillRule(Qt::WindingFill);
OuterPath.addEllipse(QPointF(60, 60), 50, 50);
OuterPath.addRect(60, 10, 50, 50);
With the example you've given we'll also need to remove a circular area from the centre of our filled shape. Let's represent that inner 'border' as a QPainterPath
and then use QPainterPath::subtracted()
to subtract InnerPath
from OuterPath
and produce our final shape:
QPainterPath InnerPath;
InnerPath.addEllipse(QPointF(60, 60), 20, 20);
QPainterPath FillPath = OuterPath.subtracted(InnerPath);
Once we've built the shape paths, we need to use them to fill/outline the shape. Let's first create a QPainter
and set it to use antialiasing:
QPainter Painter(this);
Painter.setRenderHint(QPainter::Antialiasing);
We then need to fill the shape that we've built:
Painter.fillPath(FillPath, Qt::blue);
Finally, let's paint the outlines. Note that, because we have separate paths for the inner and outer borders, we are able to stroke each border with different line thicknesses. Note also the use of QPainterPath::simplified()
: this converts the set of layered shapes into one QPainterPath
which has no intersections:
Painter.strokePath(OuterPath.simplified(), QPen(Qt::black, 1));
Painter.strokePath(InnerPath, QPen(Qt::black, 3));
If we put all of that together, it looks like this:
void Shape::paintEvent(QPaintEvent *)
{
QPainterPath OuterPath;
OuterPath.setFillRule(Qt::WindingFill);
OuterPath.addEllipse(QPointF(60, 60), 50, 50);
OuterPath.addRect(60, 10, 50, 50);
QPainterPath InnerPath;
InnerPath.addEllipse(QPointF(60, 60), 20, 20);
QPainterPath FillPath = OuterPath.subtracted(InnerPath);
QPainter Painter(this);
Painter.setRenderHint(QPainter::Antialiasing);
Painter.fillPath(FillPath, Qt::blue);
Painter.strokePath(OuterPath.simplified(), QPen(Qt::black, 1));
Painter.strokePath(InnerPath, QPen(Qt::black, 3));
}