QGraphicsRectItem 随鼠标移动.如何

QGraphicsRectItem move with mouse. How to?

本文关键字:如何 移动 鼠标 QGraphicsRectItem      更新时间:2023-10-16

我有QGraphicsViewQGraphicsSceneQGraphicsRectItemQGraphicsRectItemQGraphicsSceneQGraphicsView中的最后一个.我想通过单击鼠标移动QGraphicsRectItem!但是在我的实现中,如果我单击QGraphicsScene上的任何位置,它就会移动。无论是我的QGraphicsRectItem还是其他地方。第二个问题。该项目已移动到场景的中心。再次单击它,它开始从主位置移动。

void Steer::mousePressEvent(QMouseEvent *click)
{
    offset = click->pos();
}
void Steer::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
       p1->setPos(event->localPos() - offset); //p1 movable item
    }
}

我做错了什么?

更新:

main.cpp

#include "widget.h"
#include <QApplication>
    int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Steer w;
    w.show();
    return a.exec();
}

widget.h

#ifndef STEER_H
#define STEER_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMouseEvent>
#include <QPoint>
#include <QGraphicsRectItem>
class Steer : public QGraphicsView
{
    Q_OBJECT
private:
    QGraphicsScene *scene;
    QGraphicsRectItem *p1;
    QPoint offset;
public:
   explicit  Steer(QGraphicsView *parent = 0);
    ~Steer(){}
public slots:
    void mousePressEvent(QMouseEvent * click);
    void mouseMoveEvent(QMouseEvent * event);
};
#endif // STEER_H

widget.cpp

#include "widget.h"
#include <QBrush>
Steer::Steer(QGraphicsView *parent)
    : QGraphicsView(parent)
{
    scene = new QGraphicsScene;
    p1 = new QGraphicsRectItem;
    //add player
    p1->setRect(760, 160, 10, 80);
    //add scene
    scene->setSceneRect(0, 0, 800, 400);
    //add moveable item
    scene->addItem(p1);
    //set scene
    this->setScene(scene);
    this->show();
}
void Steer::mousePressEvent(QMouseEvent *click)
{
    offset = click->pos();
}
void Steer::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
       p1->setPos(event->localPos() - offset);
    }
}

我会尝试一种更容易理解的不同方法:

#include <QtWidgets>
class Steer : public QGraphicsView
{
public:
    Steer()
    {
        scene = new QGraphicsScene;
        p1 = new QGraphicsRectItem;
        //add player
        p1->setRect(0, 0, 10, 80);
        p1->setX(760);
        p1->setY(160);
        //add scene
        scene->setSceneRect(0, 0, 800, 400);
        //add moveable item
        scene->addItem(p1);
        //set scene
        this->setScene(scene);
        this->show();
    }
protected:
    void mousePressEvent(QMouseEvent * click)
    {
        if (p1->contains(p1->mapFromScene(click->localPos()))) {
            lastMousePos = click->pos();
        } else {
            lastMousePos = QPoint(-1, -1);
        }
    }
    void mouseMoveEvent(QMouseEvent * event)
    {
        if(!(event->buttons() & Qt::LeftButton)) {
            return;
        }
        if (lastMousePos == QPoint(-1, -1)) {
            return;
        }
        p1->setPos(p1->pos() + (event->localPos() - lastMousePos));
        lastMousePos = event->pos();
    }
private:
    QGraphicsScene *scene;
    QGraphicsRectItem *p1;
    QPoint lastMousePos;
};
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Steer w;
    w.show();
    return a.exec();
}

这里有几点需要指出:

  1. 不要使用 setRect() 来设置QGraphicsRectItem的位置。它不像你想象的那样工作。始终使用setPos()更改项目的位置。

  2. 将偏移量重命名为更具描述性的名称。我选择了lastMousePos.不要只在按下鼠标时更新一次,还要在移动鼠标时更新它。然后,只需获取两点之间的差异并将其添加到项目的位置即可。

  3. 在对移动事件做出反应之前,检查鼠标是否实际位于项目上。如果鼠标不在项目上,则需要某种方法来知道这一点,因此QPoint(-1, -1) .为此,您可能希望使用单独的布尔标志。这解决了您看到的问题,可以单击场景中的任意位置以移动项目。

    另外,请注意mapFromScene()调用:contains()函数在本地坐标中工作,因此我们必须在测试它是否在项目上方之前映射场景坐标中的鼠标位置。

  4. 事件函数不是插槽,它们是虚拟的、受保护的函数。

<小时 />

您还可以考虑在项目本身中处理这些事件。您不需要从 QGraphicsView 内执行此操作,特别是如果您有多个需要用鼠标拖动的这些项目。