There is a class class Edge : public QGraphicsItem , which implements drawing arrows from one vertex ( Node ) to another (screenshot below).
Now you need to add the ability to draw an arrow on yourself (namely the arc).
And here I have a problem. I can not correctly draw an arc and its correct selection area.
Below is the code where I either draw the arrow or the arc. Full project on github .

 Edge::Edge(Node *sourceNode, Node *destNode) : id(_idStatic++), arrowSize(15) { setFlag(QGraphicsItem::ItemIsSelectable); source = sourceNode; dest = destNode; source->addEdge(this); if(source != dest) dest->addEdge(this); adjust(); } QPolygonF Edge::nPolygonMath() const { QPolygonF nPolygon; if (source != dest) { QLineF line = QLineF(sourcePoint.x(), sourcePoint.y(), destPoint.x(), destPoint.y()); qreal radAngle = line.angle() * M_PI / 180; qreal selectionOffset = 3; qreal dx = selectionOffset * sin(radAngle); qreal dy = selectionOffset * cos(radAngle); QPointF offset1 = QPointF(dx, dy); QPointF offset2 = QPointF(-dx, -dy); nPolygon << line.p1() + offset1 << line.p1() + offset2 << line.p2() + offset2 << line.p2() + offset1; } else { nPolygon << mapFromItem(source, -Node::Radius, -Node::Radius) << mapFromItem(source, Node::Radius, -Node::Radius) << mapFromItem(source, Node::Radius, Node::Radius) << mapFromItem(source, -Node::Radius, Node::Radius); } return nPolygon; } QRectF Edge::boundingRect() const { if (!source || !dest) return QRectF(); return nPolygonMath().boundingRect(); } QPainterPath Edge::shape() const{ QPainterPath ret; ret.addPolygon(nPolygonMath()); return ret; } void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) { if (!source || !dest) return; painter->setPen(QPen((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); if (source != dest) { QLineF line(sourcePoint, destPoint); if (qFuzzyCompare(line.length(), qreal(0.))) return; // Draw the line itself painter->drawLine(line); // Draw the arrows double angle = std::atan2(-line.dy(), line.dx()); QPointF destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 1.8) * qMin(arrowSize, line.length()), cos(angle - M_PI / 1.8) * qMin(arrowSize, line.length())); QPointF destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length()), cos(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length())); painter->setBrush((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black)); painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); } else { painter->drawArc(mapFromItem(source, Node::Radius, 0).x(), mapFromItem(source, Node::Radius, 0).y(), 2 * Node::Radius, 2 * Node::Radius, 16 * -90, 16 * 180); } } 

Now the arrow is highlighted in blue

    1 answer 1

    For this, I started to push off from the center of the top. The center of the arc is placed in (center Vershiny. X + radius Versions, the center of the vertices. Y - radius Vers).
    The shape() overload for selection drew a circle with a radius of 2 pixels more to fit the thickness of the handle ( QPen ).
    The overloading of boundingRect() based on shape ().
    In the overload paint(...) drew an arc from -70 degrees to 270. -70 so that it would not get out of the lines of the arrows.
    The project is still on the githaba. Can someone help)

     void Edge::adjust() { if (!source || !dest) return; if(source != dest) { QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0)); qreal length = line.length(); prepareGeometryChange(); if (length > qreal(2 * Node::Radius)) { QPointF edgeOffset((line.dx() * Node::Radius) / length, (line.dy() * Node::Radius) / length); sourcePoint = line.p1() + edgeOffset; destPoint = line.p2() - edgeOffset; // Нахождение точки для текста QLineF line1(sourcePoint, destPoint), line2; if (line1.angle() >= 0 && line1.angle() <= 180) { line1.setLength(line1.length() - 30); line2.setPoints(line1.p2(), line1.p1()); } else { QLineF line11(destPoint, sourcePoint); line11.setLength(30); line2.setPoints(line11.p2(), line11.p1()); } QLineF line3 = line2.normalVector(); line3.setLength(12); textPoint = line3.p2(); } else { sourcePoint = destPoint = line.p1(); } } else { textPoint = QPointF(boundingRect().center().x() - Node::Radius / 2, boundingRect().center().y()); prepareGeometryChange(); sourcePoint = mapFromItem(source, 0, -Node::Radius); destPoint = mapFromItem(source, Node::Radius, 0); } } // Для столкновений и выделения QPainterPath Edge::shape() const{ QPainterPath path; if (source != dest) { QLineF line = QLineF(sourcePoint.x(), sourcePoint.y(), destPoint.x(), destPoint.y()); qreal radAngle = line.angle() * M_PI / 180; qreal selectionOffset = 3; qreal dx = selectionOffset * sin(radAngle); qreal dy = selectionOffset * cos(radAngle); QPointF offset1 = QPointF(dx, dy); path.moveTo(line.p1() + offset1); path.lineTo(line.p1() - offset1); path.lineTo(line.p2() - offset1); path.lineTo(line.p2() + offset1); } else { path.addEllipse(source->pos() + QPointF(Node::Radius, -Node::Radius), Node::Radius + 2, Node::Radius + 2); } return path; } // Для отрисовки QRectF Edge::boundingRect() const { if (!source || !dest) return QRectF(); if (source != dest) { QPolygonF pText; qreal x = textPoint.x(); qreal y = textPoint.y(); pText << QPointF(x, y) << QPointF(x, y - 110) << QPointF(x + 70, y - 110) << QPointF(x + 70, y + 10) << QPointF(x, y + 10); return shape().boundingRect().united(pText.boundingRect()); } return shape().boundingRect(); } void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) { if (!source || !dest) return; double angle; QPointF peak, destArrowP1, destArrowP2; painter->setPen(QPen((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); if (source != dest) { QLineF line(sourcePoint, destPoint); if (qFuzzyCompare(line.length(), qreal(0.))) return; // Draw the line itself painter->drawLine(line); // Draw the arrows angle = std::atan2(-line.dy(), line.dx()); destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 1.8) * qMin(arrowSize, line.length()), cos(angle - M_PI / 1.8) * qMin(arrowSize, line.length())); destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length()), cos(angle - M_PI + M_PI / 1.8) * qMin(arrowSize, line.length())); peak = line.p2(); } else { painter->drawArc(source->pos().x(), source->pos().y() - 2 * Node::Radius, 2 * Node::Radius, 2 * Node::Radius, 16 * -70, 16 * 270); angle = 1.07*M_PI; destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 1.8) * arrowSize, cos(angle - M_PI / 1.8) * arrowSize); destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 1.8)* arrowSize, cos(angle - M_PI + M_PI / 1.8) * arrowSize); painter->setBrush((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black)); peak = destPoint; } painter->setBrush((option->state & QStyle::State_Selected ? Qt::cyan: Qt::black)); painter->drawPolygon(QPolygonF() << peak << destArrowP1 << destArrowP2); painter->drawText(textPoint, "x2 y2"); } 

    Result!