如何使用QPainter或QPainterPath使用一个形状或一组连接的形状在Qt中绘制自定义形状

时间:2012-11-10 02:09:08

标签: c++ qt qpainter

我怎样才能画出像泪一样的形状?我需要绘制而不使用多个形状(椭圆和多边形),因为QPen将为每个形状绘制。我需要连接形状来创建一个新形状,或者告诉QT加入两个形状的边界,如下所示:

tear

2 个答案:

答案 0 :(得分:18)

如果您想要绘制的形状可以表示为其他形状的分层,就像您链接到的图像一样,这很容易做到:

首先,我们需要构建一个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));
}

答案 1 :(得分:3)

如果没有良好的数学背景,这实际上很难做到。如果您知道创建该形状的公式,则可以将其放入QGraphicsItem::paint()函数中。但也有一些选择:

  1. 在Inkscape(免费)等矢量编辑程序中制作图像,将其另存为.svg文件,然后将其加载到QGraphicsSvgItem。 (这就是我要做的。)

  2. 查看QPainterPath::cubicTo(),它可以让您制作贝塞尔曲线