1

我正在尝试遵循此示例和 eyllanesc 的答案 拖动 QGraphicsItem以在两个 draggable/movable 之间绘制一条以箭头结尾的线时QGraphicsRectItem的奇怪行为

这是我的代码:

自定义QGraphicsPathItem类(继承自 QObject 也是因为我使用信号):

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}

自定义qgraphicsitem 类(也继承自 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的答案,我的问题是我可以从但是画线:

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

一张图片解释了我正在尝试做的事情

在此处输入图像描述

(方块真的是用qt做的,但是线条是用油漆做的,方块是可移动的)。

简而言之:只是试图在两点(两个正方形的位置)之间画一条线,并且正方形是可移动的,因此如果移动了 2 个正方形之一,则该线应该适应。

4

1 回答 1

2

所需的内容与我在此答案中实现的内容非常相似,因此我将限制从转换为的代码:

组件.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

组件.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);
}

箭头.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

箭头.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);
于 2021-01-10T00:44:40.213 回答