如果你想要绘制的形状可以表示为其他形状的层叠,就像你提供的图像一样,那么这很容易实现:
首先,我们需要建立一个QPainterPath
来表示形状的外边缘。我们通过叠加更简单的形状来构建它;在你的示例中,我们需要一个圆和一个正方形。请注意使用QPainterPath::setFillRule(Qt::WindingFill)
:这将影响路径绘制的方式(尝试删除它以查看差异!)。
QPainterPath OuterPath;
OuterPath.setFillRule(Qt::WindingFill);
OuterPath.addEllipse(QPointF(60, 60), 50, 50);
OuterPath.addRect(60, 10, 50, 50);
根据您给出的示例,我们还需要从填充的形状中删除一个圆形区域。 让我们将那个内部的“边框”表示为 QPainterPath
,然后使用 QPainterPath::subtracted()
函数将InnerPath
从OuterPath
中减去,以生成我们的最终形状:
QPainterPath InnerPath;
InnerPath.addEllipse(QPointF(60, 60), 20, 20);
QPainterPath FillPath = OuterPath.subtracted(InnerPath);
我们建立形状路径后,需要使用它们来填充/描边形状。让我们首先创建一个 QPainter
并将其设置为使用抗锯齿:
QPainter Painter(this);
Painter.setRenderHint(QPainter::Antialiasing);
我们随后需要填充我们已经构建的形状:Painter.fillPath(FillPath, Qt::blue);
最后,让我们画出轮廓线。请注意,由于内边框和外边框有不同的路径,我们可以使用不同的线宽对每个边框进行描边。还要注意使用QPainterPath::simplified()
:这将把多层形状集合转换为一个没有交点的QPainterPath
:
Painter.strokePath(OuterPath.simplified(), QPen(Qt::black, 1));
Painter.strokePath(InnerPath, QPen(Qt::black, 3));
如果将所有这些内容放在一起,它会看起来像这样: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));
}
如果没有良好的数学背景,这实际上是相当困难的。如果您知道创建该形状的公式,只需将其放入您的QGraphicsItem :: paint()
函数中即可。但有一些替代方法:
在向量编辑程序(如Inkscape)中制作图像(免费),将其保存为.svg文件,然后将其加载到QGraphicsSvgItem中。(这就是我会做的事情。)
查看QPainterPath :: cubicTo(),它允许您制作贝塞尔曲线。