两个可移动的 QGraphicsRectItem 之间的 QGraphicsPathItem

QGraphicsPathItem between two movable QGraphicsRectItem

我正在尝试关注 this example 和 eyllanesc 的回答 在两个 draggable/movable QGraphicsRectItems

之间画一条以箭头结尾的线

这是我的代码:

自定义的QGraphicsPathItemclass(继承自QObject也是因为我用到了signals):

wireArrow.h


public slots:
    void changePosStart(QPointF newpos);
    void changePosEnd(QPointF newpos);

private:
    component *myStartItem;
    component *myEndItem;
    QPolygonF arrowHead;
    QColor myColor = Qt::black;

WireArrow.cpp

WireArrow::WireArrow(component *startItem, component *endItem,
                                  QGraphicsItem *parent )
            : QGraphicsPathItem(parent), myStartItem(startItem), myEndItem(endItem)

{

    connect(startItem,SIGNAL(componentPosChanged(QPointF)),this, SLOT(changePosStart(QPointF))   );
);
    connect(endItem,SIGNAL(componentPosChanged(QPointF)),this,SLOT(changePosEnd(QPointF)) );;

    this->setPos(myStartItem->pos());
    setFlag(ItemIsSelectable);
    setPen(QPen(myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

//    QPainterPath path;
//    path.quadTo(100,0,100,100);

    QPainterPath rectPath;
        rectPath.moveTo(0.0, 0.0);
        rectPath.lineTo(myStartItem->pos().x()-myEndItem->pos().x() , myStartItem->pos().y()-myEndItem->pos().y());



        this->setPath(rectPath);
}

void WireArrow::changePosStart(QPointF newpos)
{//@to-do: find how to update pos setpos + this->update maybe? }

void WireArrow::changePosEnd(QPointF newpos)
{//@to-do: find how to update the end pos}

自定义的qgraphicsitemclass(也继承自QObject,在位置更新时发出信号):

component::component(/*some irrelevant params*/QGraphicsItem*parent  ):
QGraphicsRectItem(parent), //...init other params
    {
        setRect(-40, -40, 80, 80);
        setFlag(ItemIsMovable);
        setFlag(ItemIsSelectable);
        setFlag(QGraphicsItem::ItemSendsScenePositionChanges);

    }

QVariant component::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{

    if (change == ItemPositionChange && scene()) {
        qDebug() << "cmp:: event change on scene";
        QPointF newPos = value.toPointF();
        emit componentPosChanged(newPos);
    }
    return QGraphicsItem::itemChange(change, value);

}


main

 // create two components out and in
WireArrow * wa = new WireArrow(out,in);
scene->addItem(wa);

我可以创建矩形(组件)并将它们移动得很好(感谢答案 ,我的问题是我可以从 out 绘制线条 origination 但是:

  1. 我无法正确地从一个组件绘制到另一个组件。
  2. 我需要让它们在拖动矩形时自动移动。在其他示例中,我看到他们将线条视为 项目,这是我不能在这里做的事情,因为电线是两个人用的 项目而不是一个所以我用 signal/slot 连接替换了它但是 我仍然不知道如何更新位置...

解释我正在尝试做的事情的图像

(方块真的是用qt画的,线是paint画的,方块是可以动的)

简而言之:只是试图在两点(两个方块的位置)之间画一条线,并且这些方块是可移动的,所以如果两个方块之一移动,该线应该适应。

所要求的与我在 so I will limit the code translated from to 中实现的非常相似:

component.h

#ifndef COMPONENT_H
#define COMPONENT_H

#include <QGraphicsRectItem>

class Arrow;

class Component : public QGraphicsRectItem
{
public:
    Component(QGraphicsItem *parent = nullptr);
    void addArrow(Arrow *arrow);
protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
    QVector<Arrow *> mArrows;
};

#endif // COMPONENT_H

component.cpp

#include "arrow.h"
#include "component.h"

Component::Component(QGraphicsItem *parent):
    QGraphicsRectItem(parent)
{
    setRect(-40, -40, 80, 80);
    setFlags(QGraphicsItem::ItemIsMovable |
             QGraphicsItem::ItemIsSelectable |
             QGraphicsItem::ItemSendsGeometryChanges);
}

void Component::addArrow(Arrow *arrow)
{
    mArrows << arrow;
}

QVariant Component::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if(change == QGraphicsItem::ItemPositionHasChanged){
        for(Arrow * arrow: qAsConst(mArrows)){
            arrow->adjust();
        }
    }
    return QGraphicsRectItem::itemChange(change, value);
}

arrow.h

#ifndef ARROW_H
#define ARROW_H

#include <QGraphicsPathItem>

class Component;

class Arrow : public QGraphicsPathItem
{
public:
    Arrow(Component *startItem, Component *endItem, QGraphicsItem *parent = nullptr);
    void adjust();
private:
    Component *mStartItem;
    Component *mEndItem;
};

#endif // ARROW_H

arrow.cpp

#include "arrow.h"
#include "component.h"

#include <QPen>

Arrow::Arrow(Component *startItem, Component *endItem, QGraphicsItem *parent):
    QGraphicsPathItem(parent), mStartItem(startItem), mEndItem(endItem)
{
    mStartItem->addArrow(this);
    mEndItem->addArrow(this);
    setPen(QPen(QColor("red"), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    adjust();
}

void Arrow::adjust()
{
    prepareGeometryChange();
    QPainterPath path;
    path.moveTo(mStartItem->pos());
    path.lineTo(mEndItem->pos());
    setPath(path);
}
Component *comp1 = new Component;
Component *comp2 = new Component;

comp1->setPos(50, 50);
comp2->setPos(400, 400);

Arrow *arrow = new Arrow(comp1, comp2);
scene->addItem(comp1);
scene->addItem(comp2);
scene->addItem(arrow);