【问题标题】:The paint function reloop infinitely绘制函数无限循环
【发布时间】:2016-03-06 05:03:53
【问题描述】:

我更新了diagramscene 示例以绘制窄线的法线。我将此行添加到Arrow::paint 功能:

painter->drawLine(line());   
painter->drawLine(line().normalVector()); // this line was added
//...
//scene()->update(); //add this line make this paint function reloop infinitely

没有update,正常线不显示,如果我移动项目,它可以显示但不正确。使用 update ,一切都正确绘制,但 paint 函数无限循环。我无法解释为什么,请帮助我!

//--编辑: 我添加了originArrow::paint函数的代码:

void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
          QWidget *)
{
    if (myStartItem->collidesWithItem(myEndItem))
        return;

    QPen myPen = pen();
    myPen.setColor(myColor);
    qreal arrowSize = 20;
    painter->setPen(myPen);
    painter->setBrush(myColor);

    QLineF centerLine(myStartItem->pos(), myEndItem->pos());
    QPolygonF endPolygon = myEndItem->polygon();
    QPointF p1 = endPolygon.first() + myEndItem->pos();
    QPointF p2;
    QPointF intersectPoint;
    QLineF polyLine;
    for (int i = 1; i < endPolygon.count(); ++i) {
    p2 = endPolygon.at(i) + myEndItem->pos();
    polyLine = QLineF(p1, p2);
    QLineF::IntersectType intersectType =
        polyLine.intersect(centerLine, &intersectPoint);
    if (intersectType == QLineF::BoundedIntersection)
        break;
        p1 = p2;
    }

    setLine(QLineF(intersectPoint, myStartItem->pos()));

    double angle = ::acos(line().dx() / line().length());
    if (line().dy() >= 0)
        angle = (Pi * 2) - angle;

        QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize,
                                        cos(angle + Pi / 3) * arrowSize);
        QPointF arrowP2 = line().p1() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                        cos(angle + Pi - Pi / 3) * arrowSize);

        arrowHead.clear();
        arrowHead << line().p1() << arrowP1 << arrowP2;
        painter->drawLine(line());
        painter->drawPolygon(arrowHead);
        if (isSelected()) {
            painter->setPen(QPen(myColor, 1, Qt::DashLine));
        QLineF myLine = line();
        myLine.translate(0, 4.0);
        painter->drawLine(myLine);
        myLine.translate(0,-8.0);
        painter->drawLine(myLine);
    }
}

//-- 更新:答案:

QRectF Arrow::boundingRect() const
{
    qreal extra = (pen().width() + 20) / 2.0;
    QLineF myVLine = line().normalVector();
    return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                      line().p2().y() - line().p1().y()))
            .normalized()
            .adjusted(-extra, -extra, extra, extra)
            .united(QRectF(myVLine.p1(), QSizeF(myVLine.p2().x() - myVLine.p1().x(),
                                               myVLine.p2().y() - myVLine.p1().y())));
}

【问题讨论】:

  • 这里没有太多代码可以帮助您调试。
  • @erip:在QCreator示例中,你可以搜索图表场景,我只添加一条线来绘制法线。
  • 嗯,这很明显为什么会发生这种情况。 update 函数调用你的绘图代码,然后又调用update 等等......你必须从其他地方调用它,而不是从绘图代码。

标签: c++ qt qgraphicsitem qpainter


【解决方案1】:

添加对 update() 的调用导致 paint() 方法被一遍又一遍地调用的原因正如 Ari0nhh 在他的评论中所说的那样——具体来说,update() 方法会导致对 paint() 的另一个调用被安排,下一次调用paint()调用update(),以此类推。这个问题的解决方案当然是不在paint()中调用update()。

但是,您真正的问题是让您觉得需要首先调用 update() 到方法中的问题:您添加的行没有正确显示。原因是您添加的代码是“作弊” - 具体来说,它试图在 Arrow 对象承诺它只会在内部绘制的区域之外绘制。因此,显示无法正确更新。

Arrow 类如何告诉 Qt 场景它将在哪里绘制?通过覆盖 boundingRect()shape() 虚拟方法。您会注意到,Arrow 类已经覆盖了这两个方法,以说明它在其行的一端添加了 arrowHead;为了正确绘制第二条线,您还需要在返回的边界矩形和形状值中包含额外线的范围。

【讨论】:

  • 谢谢。我更新了 boundingRect 函数。这行得通。
猜你喜欢
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 2021-12-17
相关资源
最近更新 更多