I have updated the diagramscene example to draw a normal line of the narrow line. I added this line to the Arrow::paint
funtions:
painter->drawLine(line());
painter->drawLine(line().normalVector()); // this line was added
//...
//scene()->update(); //add this line make this paint function reloop infinitely
Without update
, the normal line didn't show, if I move the items, it can be show but not correct. With update
, all was paint correctly but the paint
function is reloop infinitely. I cannot explain why, please help me!
//--Edit:
I add the code for the origin Arrow::paint
function:
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);
}
}
//-- Update: the answer:
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())));
}
The reason why adding a call to update() causes the paint() method to be called over and over again is as Ari0nhh said in his comment -- specifically, the update() method causes another call to paint() to be scheduled, and the next call to paint() calls update(), and so on forever. The solution to that problem, of course, is to not call update() from within paint().
Your real problem, though, is the one that caused you to feel the need to put a call to update() in to the method in the first place: your added line was not being displayed correctly. The reason for that is that your added code is "cheating" -- specifically, it's trying to draw outside of the area that the Arrow object promised it would only ever draw inside. Because of that, the display does not get updated properly.
How does the Arrow class tell the Qt scene where it will be drawing? By overriding the boundingRect() and shape() virtual methods. You'll note that the Arrow class already overrides those two methods to account for its addition of the arrowHead at one end of its line; in order to get your second line drawn properly, you'll need to include your extra line's extent in the returned bounding-rect and shape values as well.