我怎样才能画出像眼泪一样的形状?我需要在不使用多个形状(椭圆和多边形)的情况下进行绘制,因为 QPen 将为每个形状绘制。我需要连接形状来创建一个新形状,或者告诉 QT 连接两个形状的边框,如下所示:
2 回答
如果您要绘制的形状可以表示为其他形状的分层,就像您链接到的图像一样,这很容易做到:
首先,我们需要构建一个QPainterPath
来表示形状的外边缘。我们通过将更简单的形状分层来构建它;在您的示例中,我们需要一个圆形和一个正方形。注意使用QPainterPath::setFillRule(Qt::WindingFill)
: 这将影响路径的绘制方式(尝试删除它以查看差异!)。
QPainterPath OuterPath;
OuterPath.setFillRule(Qt::WindingFill);
OuterPath.addEllipse(QPointF(60, 60), 50, 50);
OuterPath.addRect(60, 10, 50, 50);
在您给出的示例中,我们还需要从填充形状的中心移除一个圆形区域。让我们将内部“边界”表示为 a 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(),它允许你制作贝塞尔曲线