QGraphicsPolygonItem在拖动时未更新QPolygonF坐标

QGraphicsPolygonItem not updating QPolygonF co-ordinates when dragged

本文关键字:更新 QPolygonF 坐标 拖动 QGraphicsPolygonItem      更新时间:2023-10-16

我有一个自定义版本的QGraphicsPolygonItem,它在这里定义:

#ifndef CUSTOMGPOLYGON_H
#define CUSTOMGPOLYGON_H
#include <QObject>
#include <QGraphicsPolygonItem>
#include <string>
#include <QGraphicsSceneMouseEvent>
#include <QMenu>
#include <QGraphicsTextItem>
class CustomGPolygon : public QObject, public QGraphicsPolygonItem
{
Q_OBJECT
public:
CustomGPolygon(QPolygonF poly, QObject *parent);
~CustomGPolygon();
using QGraphicsPolygonItem::boundingRect;
using QGraphicsPolygonItem::paint;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
QGraphicsTextItem *className;
private slots:
void deletePolygon();
void copyPolygon();

signals:
void duplicatePoly(QPolygonF);
private:
QMenu menu;
};
#endif // CUSTOMGPOLYGON_H

这是我的CustomGPolygon:的.cpp

#include "customgpolygon.h"
#include <iostream>
CustomGPolygon::CustomGPolygon(QPolygonF poly, QObject *parent):QGraphicsPolygonItem(poly)
{
menu.addAction("Copy", this, SLOT(copyPolygon()));
menu.addAction("Delete", this, SLOT(deletePolygon()));
connect(this, SIGNAL(duplicatePoly(QPolygonF)), parent, SLOT(drawPolygon(QPolygonF)));
}
CustomGPolygon::~CustomGPolygon()
{}
void CustomGPolygon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
QGraphicsItem::mouseMoveEvent(event);
QPolygonF poly = this->polygon();
QPointF edgePoint(0,0);
for(int i = 0; i<poly.size(); i++){
if(poly.at(i).x() > edgePoint.x() && poly.at(i).y() > edgePoint.y())
{
edgePoint.setX(poly.at(i).x());
edgePoint.setY(poly.at(i).y());
}
}
this->className->setPos(edgePoint);
}
}
void CustomGPolygon::deletePolygon()
{
delete this;
}
void CustomGPolygon::copyPolygon()
{
QPolygonF poly = this->polygon();
emit duplicatePoly(poly);
}

要在我的QGraphicsScene上绘制其中一个多边形,我在我的主窗口.cpp中使用以下函数:

void MainWindow::drawPolygon(const QPolygonF &poly)
{
CustomGPolygon *objectPt = new CustomGPolygon(poly, this);
objectPt->setPen(pen);
objectPt->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(objectPt);
objectPt->className = textItem;
map->drawing = false;
}

当我拖动这个绘制的多边形时,我需要边界Rect内向量的坐标来更新——目前,他们还没有这样做。

我尝试添加这些标志来解决问题:

objectPt->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
objectPt->setFlag(QGraphicsItem::ItemSendsScenePositionChanges);

然而问题仍然存在

项目中设置的QPolygonF与场景的坐标无关,而是与项目的坐标有关,因此移动项目不会更改QPolygonF。这与我们的脸的位置相似:如果道路是相对于世界而不是相对于我们自己移动的。因此,如果要获得相对于场景的多边形,则必须使用mapToScene((方法进行转换。另一方面,如果要跟踪项的位置,则不应使用mouseMoveEvent((,而应使用itemChange((。

另一方面,你对点的计算是不正确的,你应该比较的是基于某种度量的距离,例如欧几里得距离,因为例如,根据你的逻辑,如果多边形位于负坐标的位置,那么edgePoint将始终为(0,0(。

考虑到以上情况,解决方案是:

#include <QtWidgets>
class CustomGPolygon: public QObject, public QGraphicsPolygonItem{
Q_OBJECT
public:
CustomGPolygon(QPolygonF poly, QObject *parent=nullptr):
QObject(parent), QGraphicsPolygonItem(poly), className(nullptr){
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
menu.addAction("Copy", this, &CustomGPolygon::copyPolygon);
menu.addAction("Delete", this,  &CustomGPolygon::deletePolygon);
// if(parent)
// connect(this, &CustomGPolygon:: SIGNAL(duplicatePoly(QPolygonF)), parent, SLOT(drawPolygon(QPolygonF)));
}
~CustomGPolygon(){}
QGraphicsTextItem *getClassName() const{return className;}
void setClassName(QGraphicsTextItem *value){className = value;}
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value){
if(change == GraphicsItemChange::ItemPositionChange && !polygon().isEmpty()){
QPolygonF p = mapToScene(polygon());
QPointF edgePoint = *std::max_element(p.begin(), p.end(),
[](const QPointF & x, const QPointF & y) -> bool
{
return QVector2D(x).length() > QVector2D(y).length();
});
if(className)
className->setPos(edgePoint);
}
return QGraphicsPolygonItem::itemChange(change, value);
}
private Q_SLOTS:
void deletePolygon(){delete this;}
void copyPolygon(){
QPolygonF poly = mapToScene(polygon());
Q_EMIT duplicatePoly(poly);
}
Q_SIGNALS:
void duplicatePoly(QPolygonF);
private:
QGraphicsTextItem *className;
QMenu menu;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
QPolygonF poly;
poly << QPointF(0, 0) << QPointF(100, 0) << QPointF(100, 100);
CustomGPolygon *item = new CustomGPolygon(poly);
QGraphicsTextItem *textItem = new QGraphicsTextItem("Stack Overflow");
scene.addItem(textItem);
scene.addItem(item);
item->setClassName(textItem);
view.show();
view.resize(640, 480);
return a.exec();
}
#include "main.moc"