paint函数无限循环

The paint function reloop infinitely

我已经更新了 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 函数无限循环。我无法解释为什么,请帮助我!

//--编辑: 我添加原点 Arrow::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())));
}

之所以添加对 update() 的调用会导致 paint() 方法被一遍又一遍地调用,正如 Ari0nhh 在他的评论中所说的那样——具体来说,update() 方法会导致对 paint( ) 进行调度,下一次调用 paint() 调用 update(),等等。当然,该问题的解决方案是不要从 paint() 中调用 update()。

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

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