QGraphicsPolygonItem не обновляет координаты QPolygonF при перетаскивании - PullRequest
1 голос
/ 26 февраля 2020

У меня есть пользовательская версия 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

Это. cpp для моего CustomGPolygon:

#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;
}

Когда я перетаскиваю этот нарисованный многоугольник, мне нужно обновить координаты векторов в пределах boundingRect - что на момент, они не делают.

Я попытался добавить эти флаги для решения проблемы:

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

Однако проблема осталась

1 Ответ

1 голос
/ 26 февраля 2020

QPolygonF, установленный в элементе, относится не к координатам сцены, а к координатам элемента, поэтому перемещение элемента не изменит QPolygonF. Это похоже на положение нашего лица: если дороги движутся относительно мира, но не относительно нас самих. Поэтому, если вы хотите получить многоугольник относительно сцены, вам нужно будет выполнить преобразование с помощью метода mapToScene (). С другой стороны, если вы хотите отслеживать положение элемента, вам не следует использовать mouseMoveEvent (), а itemChange ().

С другой стороны, ваше вычисление точки неверно, то вы должны сравнить расстояние, основанное на некотором метри c, например, евклидово расстояние, так как, например, с вашими логами c, если Полигон находится в положении с отрицательными координатами, тогда 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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...