问题描述
我正在尝试关注 this example 和 eyllanesc 的回答
Weird behaviour when dragging QGraphicsItem 在两个可拖动/可移动 QGraphicsRectItem
s
这是我的代码:
定制的 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,SLOT(changePosEnd(QPointF)) );;
this->setPos(myStartItem->pos());
setFlag(ItemIsSelectable);
setPen(QPen(myColor,2,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
// QPainterPath path;
// path.quadTo(100,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);
我可以创建矩形(组件)并将它们移动得很好(感谢答案 here ,我的问题是我可以从 out
绘制线条起点但是:
- 我无法正确地从一个组件绘制到另一个组件。
- 我需要在拖动矩形时让它们自动移动。在其他示例中,我看到他们将线条视为 项目,这是我不能在这里做的事情,因为电线是两个 项目而不是一个,所以我用信号/插槽连接替换了它,但是 我还是不知道如何更新位置...
(方块真的是用qt做的,但线是用油漆做的,方块是可移动的)。
简而言之:只是想在两点(两个方块的位置)之间画一条线,方块是可移动的,所以如果移动了两个方块中的一个,这条线应该适应。
解决方法
所需的内容与我在 this answer 中实现的内容非常相似,因此我将限制从 python 转换为 c++ 的代码:
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,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);