Происходит вызов метода mouseMoveEvent объекта QGraphicsItem после вызова контекстного меню

У меня есть реализация класса Square, основанная на QGraphicsItem.

Класс реализован таким образом, что я мог перемещать объект в QGraphicsView.

Далее я создаю контекстное меню для объекта Square в классе GraphicsView. Проблема в том, что после того, как я нажимаю на пункт меню, а затем на произвольную область сцены левой кнопкой мыши, объект, на который я нажал, перемещается на это место.

Хотя по идее этого не должно происходить. Как решить эту проблему?

class GraphicsView : public QGraphicsView
{
    Q_OBJECT

public:
    explicit GraphicsView(QWidget* parent = nullptr)
        : QGraphicsView(parent)
    {
        setContextMenuPolicy(Qt::CustomContextMenu);
        connect(this, &GraphicsView::customContextMenuRequested, this, &GraphicsView::showContextMenu);

        scene = new QGraphicsScene(this);
        scene->setBackgroundBrush(Qt::white);
        setScene(scene);

        auto square = new Square();
        square->setPos(10, 10);
        scene->addItem(square);

        auto square2 = new Square();
        square2->setPos(50, 50);
        scene->addItem(square2);
    }
    ~GraphicsView() override = default;

    void showContextMenu(const QPoint& pos)
    {
        auto position = QPoint(pos);

        QGraphicsItem* item = scene->itemAt(mapToScene(pos), QTransform());
        if (item && dynamic_cast<Square*>(item))
        {
            QMenu contextMenu(tr("Context menu1"), this);

            QAction addBt1(tr("Btn1"), this);
            connect(&addBt1, &QAction::triggered, this, &GraphicsView::addBtn1);
            contextMenu.addAction(&addBt1);

            QAction addBtn2(tr("Btn2"), this);
            connect(&addBtn2, &QAction::triggered, this, &GraphicsView::addBtn2);
            contextMenu.addAction(&addBtn2);

            contextMenu.exec(mapToGlobal(pos));
        }
    }

    static void addBtn1()
    {
        qDebug() << "Btn1";
    }

    static void addBtn2()
    {
        qDebug() << "Btn2";
    }
    
    QGraphicsScene* scene;
};
class Square : public QObject, public QGraphicsItem
{
    Q_OBJECT

public:
    explicit Square(QObject* parent = nullptr) : QObject(parent), QGraphicsItem() {}
    ~Square() {}

private:
    QRectF boundingRect() const override { return {-3,-3,6,6}; }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
    {
        painter->setPen(Qt::black);
        painter->setBrush(Qt::green);
        painter->drawRect(-3,-3,6,6);
        Q_UNUSED(option);
        Q_UNUSED(widget);
    }

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
    {
        auto newPosition = mapToScene(event->pos());
        QPointF positionMirrorDifference = newPosition - this->pos();
        this->setPos(newPosition);
    }
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override { Q_UNUSED(event); }
    void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override { Q_UNUSED(event); }
};

Ответы (1 шт):

Автор решения: Alexander Chernin

По идее надо делать вот так:

class Square : public QObject, public QGraphicsItem
{
//...
private:
    // Этим методом вы задаете границы объекта относительно его положения на сцене
    QRectF boundingRect() const override {
        // Позиция на сцене
        QPointF p = this->pos();
        return {
            p.x() - 3, //
            p.y() -3,
            6,
            6
        };
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
    {
        painter->setPen(Qt::black);
        painter->setBrush(Qt::green);

        // Рисуем квадрат
        painter->drawRect(boundingRect());

        Q_UNUSED(option);
        Q_UNUSED(widget);
    }

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
    {
        // Перемещаем в позицию event.pos() в координатах сцены
        this->setPos(event->pos());
    }
    //...
};
→ Ссылка