如何用QLine连接两个QGraphicsPixmapItem并实现联动拉伸?
实现QGraphicsPixmapItem的动态连线功能
问题说明
已在QGraphicsScene中添加两个QGraphicsPixmapItem,需要用QLineItem连接二者,且移动任意PixmapItem时,连线能自动拉伸保持连接。参考Qt官方Elastic Nodes Example觉得过于复杂,基于示例实现了椭圆的连线功能,但无法直接替换为QGraphicsPixmapItem,核心问题是PixmapItem的位置与中心计算逻辑和椭圆不同。
解决方案代码
#include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsPixmapItem> #include <QGraphicsLineItem> #include <QPixmap> class CustomPixmap : public QGraphicsPixmapItem { public: CustomPixmap(const QPixmap& pixmap) : QGraphicsPixmapItem(pixmap) { setFlag(QGraphicsItem::ItemIsMovable); setFlag(QGraphicsItem::ItemSendsScenePositionChanges); } void addLine(QGraphicsLineItem *line, bool isPoint1) { m_line = line; m_isP1 = isPoint1; } QVariant itemChange(GraphicsItemChange change, const QVariant &value) override { if (change == ItemPositionChange && scene()) { QPointF newPos = value.toPointF(); updateLinePosition(newPos); } return QGraphicsPixmapItem::itemChange(change, value); } private: void updateLinePosition(const QPointF& newPos) { // 计算Pixmap的中心位置:新位置 + 自身boundingRect的半宽高 QRectF bounds = boundingRect(); QPointF newCenter = newPos + QPointF(bounds.width()/2, bounds.height()/2); // 更新连线的对应端点 QLineF currentLine = m_line->line(); if (m_isP1) { currentLine.setP1(newCenter); } else { currentLine.setP2(newCenter); } m_line->setLine(currentLine); } QGraphicsLineItem* m_line = nullptr; bool m_isP1 = false; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); QGraphicsScene scene; // 加载示例图片,替换为你自己的图片路径 QPixmap pix1(":/images/pic1.png"); QPixmap pix2(":/images/pic2.png"); CustomPixmap* pixItem1 = new CustomPixmap(pix1); pixItem1->setPos(30, 30); scene.addItem(pixItem1); CustomPixmap* pixItem2 = new CustomPixmap(pix2); pixItem2->setPos(200, 200); scene.addItem(pixItem2); // 初始化连线,初始位置设为两个Pixmap的中心 QLineF initialLine(pixItem1->pos() + pixItem1->boundingRect().center(), pixItem2->pos() + pixItem2->boundingRect().center()); QGraphicsLineItem* line = scene.addLine(initialLine); pixItem1->addLine(line, true); pixItem2->addLine(line, false); QGraphicsView view(&scene); view.setSceneRect(0, 0, 400, 400); view.show(); return a.exec(); }
关键知识点
- 获取Pixmap范围:使用
boundingRect()获取QGraphicsPixmapItem的边界矩形,替代椭圆的rect()方法,这是适配PixmapItem的核心。 - 中心计算逻辑:PixmapItem的
pos()是其边界矩形的左上角坐标,因此中心位置为pos() + boundingRect().center(),移动时用新位置加上半宽高即可得到新中心。 - 位置变更监听:必须设置
ItemSendsScenePositionChanges标志,这样在item位置即将改变时,itemChange方法会收到ItemPositionChange信号,提前更新连线位置。 - 连线更新时机:在
itemChange中处理位置变更,确保连线和item移动同步,避免视觉延迟。
内容的提问来源于stack exchange,提问作者Toloka
相关产品推荐
相关产品推荐

