【问题标题】:How to draw custom shapes in Qt with QPainter or QPainterPath using one shape or a group of shapes joined如何使用 QPainter 或 QPainterPath 在 Qt 中使用一个形状或一组连接的形状绘制自定义形状
【发布时间】:2012-11-10 02:09:08
【问题描述】:

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

【问题讨论】:

    标签: c++ qt qpainter


    【解决方案1】:

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

    首先我们需要构建一个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()OuterPath 中减去 InnerPath 并生成我们的最终形状:

    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));
    }
    

    【讨论】:

    • 太棒了,这是我的问题,setFillRule,我也曾想过使用椭圆和矩形,但它们之间会产生一个空白,我也认为使用弧线和两条线来绘制这个,strokePath并且 fillPath 太我在搜索了,这个解决方案是最简单和有用的,谢谢!
    【解决方案2】:

    如果没有良好的数学背景,这实际上是相当困难的。如果您知道创建该形状的公式,则可以将其放入您的 QGraphicsItem::paint() 函数中。但也有一些替代方案:

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

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

    【讨论】:

    • 当像 OP 引用的形状可以表示为简单形状的分层时,无需使用复杂的数学来表示它。只需将简单的形状分层并使用 QPainterPath 中内置的一些功能来构建您的复杂形状。详情见我的回答。
    猜你喜欢
    • 2023-02-16
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    相关资源
    最近更新 更多