• 【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件


    说明

    在使用Qt的图形视图框架实现功能时,一般会在其基础上进行自定义功能实现。
    如:滚轮对场景的缩放,鼠标拖动场景中的项,以及可以在场景中进行右键操作等。

    示例

    myitem为自定义QGraphicsItem,实现了边框、重绘事件、鼠标悬停、按键、右键菜单等功能。

    myitem.h
    #ifndef MYITEM_H
    #define MYITEM_H
    
    #include 
    
    class MyItem : public QGraphicsItem
    {
    public:
        MyItem();
        // 边框
        virtual QRectF boundingRect() const override;
        // 重绘事件
        virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                   QWidget *widget) override;
        // 设置笔刷
        inline void setColor(const QColor &color) {brushColor = color;}
    
    protected:
        // 鼠标按下函数,设置被点击的图形项得到焦点,并改变光标外观
        virtual void keyPressEvent(QKeyEvent *event) override;
        // 键盘按下函数,判断是不是向下方向键,若是是,则向下移动图形项
        virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
        // 悬停事件函数,设置光标外观和提示
        virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
        // 右键菜单函数,为图形项添加一个右键菜单
        virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
    
    private:
        QColor brushColor; // 笔刷颜色
    };
    #endif // MYITEM_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    myitem.cpp
    #include "myitem.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define WIDTH 40
    #define HEIGHT 40
    
    #define POS 20
    
    MyItem::MyItem()
    {
        brushColor = Qt::black;
    
        setFlag(QGraphicsItem::ItemIsFocusable);
        setFlag(QGraphicsItem::ItemIsMovable);
        setAcceptHoverEvents(true);
    
    }
    
    QRectF MyItem::boundingRect() const
    {
        qreal adjust = 0.5; // 返回上下左右+0.5个像素
        return QRectF(-POS - adjust, -POS - adjust,
                      WIDTH + adjust, HEIGHT + adjust);
    }
    
    void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
                       QWidget *)
    {
        if (hasFocus()) {
            painter->setPen(QPen(QColor(255, 255, 255)));
        } else {
            painter->setPen(QPen(QColor(100, 100, 100)));
        }
        painter->setBrush(brushColor);
        painter->drawRect(-POS, -POS, WIDTH, HEIGHT);
    }
    
    void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
    {
        setFocus();
        // 设置光标为手握下的形状
        setCursor(Qt::ClosedHandCursor);
        QGraphicsItem::mousePressEvent(e);
    }
    
    void MyItem::keyPressEvent(QKeyEvent *event)
    {
        if (Qt::Key_Down == event->key())
            moveBy(0, 10);
        else if(Qt::Key_Up == event->key())
            moveBy(0, -10);
        else if(Qt::Key_Left == event->key())
            moveBy(-10, 0);
        else if(Qt::Key_Right == event->key())
            moveBy(10, 0);
        else{
    
        }
        QGraphicsItem::keyPressEvent(event);
    }
    
    void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
    {
        // 设置光标为手张开的形状
        setCursor(Qt::OpenHandCursor);
        setToolTip("click me");
    }
    
    void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
    {
        QMenu menu;
        QAction *moveAction = menu.addAction("move origin");
        QAction *selectedAction = menu.exec(event->screenPos());
        if (selectedAction == moveAction) {
            setPos(0, 0);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    myview.h

    myview继承QGraphicsView,重新实现了滚轮事件,可对场景进行缩放操作

    #ifndef MYVIEW_H
    #define MYVIEW_H
    
    #include 
    #include 
    
    class MyView : public QGraphicsView
    {
        Q_OBJECT
    public:
        explicit MyView(QWidget *parent = 0);
    
    protected:
        // 滚轮事件:缩放
        virtual void wheelEvent(QWheelEvent *event) override;
    };
    #endif // MYVIEW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    myview.cpp
    #include "myview.h"
    
    #include "myview.h"
    #include 
    
    MyView::MyView(QWidget *parent) :
        QGraphicsView(parent)
    {
    }
    
    void MyView::wheelEvent(QWheelEvent *event)
    {
        if(event->delta() > 0)
        {
            scale(1.1, 1.1);
        }else{
            scale(0.9, 0.9);
        }
        // 加上这个,否则在场景和图形项中就没法再接收到该事件了
        QGraphicsView::wheelEvent(event);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    调用
    main.cpp
    #include 
    
    #include "myitem.h"
    #include "myview.h"
    #include 
    #include 
    
    #include 
    
    
    int main(int argc, char* argv[ ])
    {
        QApplication app(argc, argv);
        qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
        QGraphicsScene scene;
        // 设置场景尺寸,减少动态渲染
        scene.setSceneRect(-300, -225, 600, 450);
    	// 创建项
        for (int i = 0; i < 5; ++i) {
            MyItem *item = new MyItem;
            item->setColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
            item->setPos(i * 50 - 100, -50);
            scene.addItem(item);
        }
    	// 声明视图
        MyView view;
        view.setScene(&scene);
        // 设置背景刷
        view.setBackgroundBrush(QBrush(QColor(220, 220, 220)));
        view.show();
    
        return app.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    效果

    显示效果如下:

    自定义图形视图

  • 相关阅读:
    面试秘籍 | 软件测试必备的mysql数据库技术
    PHP火狼大灌篮游戏源码微信+手机wap源码带控制
    QCC51XX---​ BTLinks获取key
    使用 Redis 实现分布式锁,解决分布式锁原子性、死锁、误删、可重入、自动续期等问题(使用SpringBoot环境实现)
    画画用电容笔还是触控笔?电容笔10大品牌排行榜
    MyBatis的各种查询功能
    u盘文件突然不见了怎么样才能恢复呢?
    K8S(1)Pod
    java专项练习(复制数组元素)
    springboot+mybatis-plus
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133387419