Ошибка перемещения QGraphicsItem в пользовательском QGraphicsView - PullRequest
0 голосов
/ 17 апреля 2020

У меня проблемы с перемещением QGraphicItem в пользовательский класс QGraphicView. То, что я хотел бы сделать, это выбрать элемент щелчком левой кнопки мыши и затем переместить его туда, где я сделал правый щелчок мыши.

Я сильно подозреваю, что моя проблема в том, что QGraphicsItem: : setPos () требует, чтобы координаты были в родительских координатах, и я не уверен, какой из QMouseEvent :: * Pos () использовать, и как преобразовать его в родительские координаты.

Отображает снимки того, что происходит, и того, что следует за кодом.

main. cpp: (простое основное здесь, стандартный тестовый жгут)

#include "QtTest.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QtTest w;
    w.show();
    return a.exec();

}

QtTest.h: (Это определяет главное окно приложения)

#pragma once

#include <QtWidgets/QMainWindow>

class QGraphicsView;
class QGraphicsScene;
class QGraphicsItem;
class QMouseEvent;

class QtTest : public QMainWindow
{
    Q_OBJECT

public:
    QtTest(QWidget *parent = Q_NULLPTR);

private:
    QGraphicsView*   m_gv;
    QGraphicsScene*  m_pScene;

    void setupUI();
};

QtTest. cpp: (реализация основного окна приложения)

#include "QtTest.h"
#include "testGV.h"

#include <QVariant>
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QMainWindow>
#include <QMouseEvent>
#include <QWidget>

QtTest::QtTest(QWidget *parent): QMainWindow(parent)
{
    setupUI();
}

void QtTest::setupUI()
{
    QWidget *centralWidget;

   if (objectName().isEmpty())
       setObjectName("QtTestClass");
   resize(600, 400);

   centralWidget = new QWidget(this);
   centralWidget->setObjectName("centralWidget");

   m_gv = new testGV(centralWidget);
   m_gv->setObjectName("graphicsView");
   m_gv->setGeometry(QRect(100, 10, 441, 331));

   setCentralWidget(centralWidget);
}

testGV.h: (определение пользовательского виджета)

#pragma once

#include <QGraphicsView>
#include <QGraphicsItem>

class testGV : public QGraphicsView
{
    Q_OBJECT

public:
    testGV(QWidget* parent);

protected:
    void mousePressEvent(QMouseEvent*);

private:
    QGraphicsScene*  m_pScene;
    QGraphicsItem*   m_pItem;

    void   createScene();
};

testGV. cpp: (реализация пользовательского виджета)

#include "testGV.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QMouseEvent>

testGV::testGV(QWidget* parent) : QGraphicsView(parent)
{
    createScene();
}

void testGV::createScene()
{
    m_pScene = new QGraphicsScene();
    m_pScene->addRect(QRect(30, 30, 150, 150), QPen(Qt::black), QBrush(Qt::black, Qt::NoBrush));
    QGraphicsEllipseItem* pTemp = m_pScene->addEllipse(QRect(0, 0, 15, 15), QPen(Qt::black), QBrush(Qt::red, Qt::SolidPattern));
    pTemp->setFlag(QGraphicsItem::ItemIsMovable);
    pTemp->setFlag(QGraphicsItem::ItemSendsGeometryChanges);

    setScene(m_pScene);
}

void testGV::mousePressEvent(QMouseEvent* pEvent)
{
    if (pEvent->button() == 1)                        // left button click
    {
        m_pItem = itemAt(pEvent->pos());
    }
    else if (pEvent->button() == 2)                    // right button click
    {
        m_pItem->setPos(pEvent->pos());
        m_pScene->update();
    }
}

enter image description here

Изображение слева является начальным отображением, когда я щелкаю правой кнопкой мыши на красной точке, а затем нажимаю в квадрате в точке, где находится черная точка, я получаю изображение справа. Что мне нужно, так это красная точка, которая перемещается туда, куда я нажал.

1 Ответ

0 голосов
/ 17 апреля 2020

Причиной проблемы является то, что QMouseEvent имеет информацию о положении в координатах вида, но элемент использует координаты сцены. Решение в этом случае состоит в том, чтобы сопоставить координаты вида с координатами сцены:

void testGV::mousePressEvent(QMouseEvent* pEvent)
{
    if (pEvent->button() == Qt::LeftButton)
        m_pItem = itemAt(pEvent->pos());
    else if (pEvent->button() == Qt::RightButton)
        if(m_pItem)
            m_pItem->setPos(mapToScene(pEvent->pos()));
}

Но даже при этом возникает проблема, положение ваших элементов относительно topLeft, поэтому смещение будет иметь ошибку, если вы хотите избежать этого отклонения, вы должны учитывать положение левого щелчка:

void testGV::mousePressEvent(QMouseEvent* pEvent)
{
    if (pEvent->button() == Qt::LeftButton){
        m_pItem = itemAt(pEvent->pos());
        m_pItem->setData(0, mapToScene(pEvent->pos()));
    }
    else if (pEvent->button() == Qt::RightButton)
        if(m_pItem){
            QPointF p = m_pItem->data(0).toPointF();
            QPointF sp = mapToScene(pEvent->pos());
            m_pItem->setPos(m_pItem->pos() + sp - p);
            m_pItem->setData(0, sp);
        }
}

Примечание: Когда указатель создан, он указывает на любой расположение в памяти, что может вызвать проблемы, поэтому я рекомендую инициализировать его как nullptr, а также проверить правильность указателя:

testGV::testGV(QWidget* parent) : QGraphicsView(parent), <b>m_pItem(nullptr)</b>
{
    createScene();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...