Qt GraphicsView Event

目录 Content
[hide]

Qt 提供了 scene、view、item 框架,对于交互事件很多依赖于鼠标操作,本篇对此进行概括和总结。

〇、事件处理顺序

鼠标事件处理程序顺序  view -> scene -> item

如果重写了事件方法,则应该在重写方法末尾调用父类的事件方法,以便传递事件。

一、View

view 的鼠标事件是 QMouseEvent

1、鼠标移动事件 mouseMoveEvent

#include <QGraphicsView>
#include <QObject>

class MyView : public QGraphicsView
{
    Q_OBJECT
public:
    MyView(QWidget *parent = nullptr);

protected:
    void mouseMoveEvent(QMouseEvent *event) override;
};

鼠标移动事件只有在鼠标按键按下才会发生,除非通过 setMouseTracking()  启用鼠标追踪。(也可以在Design中启用这个属性)

#include "myview.h"
#include <QDebug>
#include <QMouseEvent>

MyView::MyView(QWidget *parent)
    :QGraphicsView(parent)
{
    setMouseTracking(true);//默认为 false,需奥鼠标移动时至少按住一个鼠标按键,才会接收移动事件。

}

void MyView::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "view mouse move " << event->pos();

}

但是如果想事件传向 scene ,则需要在 mouseMoveEvent 事件中继续传递事件

void MyView::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "view mouse move " << event->pos();
    QGraphicsView::mouseMoveEvent(event);
}

event->pos() 给出的是 鼠标光标在 view 的坐标,类型为  QPoint ,整型。

2、滚轮事件 wheelEvent

滚轮事件来自于鼠标滚轮和触摸板滚动手势。在 view 中可以用来放大和旋转。

protected:
    void wheelEvent(QWheelEvent *event) override;

private:
    QPointF sceneMousePos;

实现

void MyGraphicsView::wheelEvent(QWheelEvent *event)
{
    if (event->orientation() == Qt::Vertical)
    {
        double angleDeltaY = event->angleDelta().y();
        double zoomFactor = qPow(1.0015, angleDeltaY);
        this->scale(zoomFactor, zoomFactor);
        
        if(angleDeltaY > 0)
        {
            this->centerOn(sceneMousePos);
            sceneMousePos = this->mapToScene(event->pos());
        }
        this->viewport()->update();
        event->accept();
    }else{
        event->ignore();
    }
}

 

二、scene

scene 的鼠标事件是  QGraphicsSceneMouseEvent

1、鼠标移动事件 mouseMoveEvent

#include <QGraphicsScene>
#include <QObject>


class MyScene : public QGraphicsScene
{
    Q_OBJECT

public:
    explicit MyScene(QObject *parent = nullptr);

protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
};
#include "myscene.h"

#include <QtDebug>
#include <QGraphicsSceneMouseEvent>

MyScene::MyScene(QObject *parent)
    :QGraphicsScene(parent)
{

}

void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "scene mouse move" << event->scenePos();
    QGraphicsScene::mouseMoveEvent(event);

}

三、Item

Item 的鼠标事件是  QGraphicsSceneMouseEvent

1、鼠标移动事件 mouseMoveEvent

#include <QGraphicsPixmapItem>
#include <QObject>

class MyPixmapItem : public QGraphicsPixmapItem
{
public:
    MyPixmapItem();

protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) ;
};

Item 需要被选择后,才会接收鼠标事件,用 setFlag(QGraphicsItem::ItemIsSelectable)。

#include "mypixmapitem.h"

#include 
#include 

MyPixmapItem::MyPixmapItem()
{
    setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);

}

void MyPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    
    qDebug() << "Item mouse move event->pos() : " << event->pos(); //光标在 item 中的坐标
    qDebug() << "Item mouse move mapToScene(event->pos())" << mapToScene(event->pos()); //光标在 scene 中的坐标
    qDebug() << "Item pos is " << pos(); //Item 的位置坐标
    QGraphicsItem::mouseMoveEvent(event);

}

 

四、QtCreator 技巧

1、如何快速敲出鼠标事件代码?

比如在自定义的 view 头文件里,敲入 void m 即可触发自动完成功能,跳出列表供选择。但是在 QGraphicsItem 可以,而在 QGraphicsPixmapItem 却不会自动跳出。

 

延伸阅读

  • Qt中基于QGraphicsItem类的重载鼠标事件函数的教训
    https://blog.csdn.net/xj178926426/article/details/7084205
  • QGraphicsPixmapItem与QGraphicsScene的编程实例
    https://blog.csdn.net/hechangfei/article/details/85699489

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.