[Solved] Trouble creating an arrow between two QGraphicsItems
-
I am trying to implement some kind of node graph GUI. I started the work based on the "Diagram Scene":http://qt-project.org/doc/qt-5.0/qtwidgets/graphicsview-diagramscene.html and the "Elastic Node":http://qt-project.org/doc/qt-5.0/qtwidgets/graphicsview-elasticnodes.html examples. I have some difficulties however in customizing the nodes and draw arrows between them.
So far, I subclassed the QGraphicsProxyWidget class to create some kind of dialog looking node. The node is further customized by adding labels and connectors, which are subclasses of QGraphicsPathItem.
!http://i41.tinypic.com/67uy9s.jpg(Nodes)!
The problem is that the arrow never appear. I managed however to make it work between the connectors alone.
!http://i43.tinypic.com/339mums.jpg(Nodes and arrow)!
Here's my code to draw the arrow (almost the same as the Diagram Scene example).
@void NodeLinkItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
painter->setPen(pen());
painter->setBrush(Qt::white);// Don't paint the arrow if both connectors are superposed if (m_sourceConnector->collidesWithItem(m_destConnector))
return;
// Draw the line part of the arrow QLineF centerLine(m_sourceConnector->pos(), m_destConnector->pos()); QPolygonF endPolygon = m_destConnector->path().toFillPolygon(); QPointF p1 = endPolygon.first() + m_destConnector->pos();
QPointF p2;
QPointF intersectPoint;
QLineF polyLine;for (int i = 1; i < endPolygon.count(); ++i) {
p2 = endPolygon.at(i) + m_destConnector->pos();
polyLine = QLineF(p1, p2);
QLineF::IntersectType intersectType = polyLine.intersect(centerLine, &intersectPoint);
if (intersectType == QLineF::BoundedIntersection)
break;
p1 = p2;
}setLine(QLineF(intersectPoint, m_sourceConnector->pos())); // Draw the arrowhead part of the arrow double angle = std::acos(line().dx() / line().length());
if (line().dy() >= 0)
angle = (PI * 2) - angle;qreal arrowSize = 10; QPointF arrowP1 = line().p1() + QPointF(std::sin(angle + PI / 3) * arrowSize, std::cos(angle + PI / 3) * arrowSize); QPointF arrowP2 = line().p1() + QPointF(std::sin(angle + PI - PI / 3) * arrowSize, std::cos(angle + PI - PI / 3) * arrowSize); m_arrowhead.clear(); m_arrowhead << line().p1() << arrowP1 << arrowP2;
painter->drawLine(line());
painter->drawPolygon(m_arrowhead);if (isSelected()) {
painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
QLineF linkLine = line();
double a = linkLine.angle();
double d = 4;linkLine.translate(d * std::sin(a / 180 * PI), d * std::cos(a / 180 * PI)); painter->drawLine(linkLine); linkLine.translate(2 * d * std::sin((a - 180) / 180 * PI), 2*d*std::cos((a - 180) / 180 * PI)); painter->drawLine(linkLine);
}
}
@Any idea why it wouldn't work when the connector is inside another node? Is it possible that the coordinates returned around lines 15-17 are in parent coordinates, aka. coordinates inside the node?
-
From documentation:
Items live in their own local coordinate system.
- QGraphicsItem::pos() - Returns the position of the item in parent coordinates.
- QGraphicsItem::scenePos() - Returns the item's position in scene coordinates.
Items NodeLinkItem, m_sourceConnector, m_destConnector have the same parent?
-
I was just about to try reparenting the objects:
- I don't set any parent for NodeLinkItem.
- m_sourceConnector and m_destConnector are of type NodeConnectorItem.
- NodeConnectorItem are instanciated when NodeItem objects are created, and I set the new node as parent for every of it's Connectors.
So I suppose since the connector has a NodeItem as parent, connectors return coordinates relative to this node. I'll try setting no parents to the connectors.
-
_<
For unknown reasons, the connectors are not painted if I don't set their parent node. However, using scenePos() instead of pos() fixed everything. Thank you for your answer.
-
Always happy to help!