图形视图框架 事件处理(item)

在图形界面框架中的事件都是先由视图进行接收,然后传递给场景,再由场景传递给图形项。通过键盘处理的话,需要设置焦点,在QGraphicsScene中使用setFoucesItem()函数可以设置焦点,或者图形项使用setFouce()获取焦点。

默认的如果场景中没有获取焦点,那么所有的键盘事件将会被丢弃。如果场景中的setFouce()函数或图形项获取了焦点,那么场景也会自动获取焦点。

对于鼠标悬停效果,QGraphicsScene会调度悬停事件。如果一个图形项可以接收悬停事件,那么当鼠标进入它的区域之中时,它就会收到一个GraphicsSceneHoverEnter事件。如果鼠标继续在图形项的区域之中进行移动,那么QGraphicsScene就会向该图形项发送GraphicsSceneHoverMove事件。当鼠标离开图形项的区域时,它将会收到一个GraphicsSceneHoverLeave事件。图形项默认是无法接收悬停事件的,可 以使用QGraphicsItem类的setAcceptHoverEvents()函数使图形项可以接收悬停事件。

所有的鼠标事件都会传递到当前鼠标抓取的图形项,一个图形项如果可以接收鼠标事件(默认可以)而且鼠标在它的上面被按下,那么它就会成为场景的鼠标抓取的图形项

事件主要分为:

  • 鼠标事件
  • 悬停事件
  • 键盘事件
  • 拖拽事件
  • 上下文菜单事件

由于内容比较多,这里就单个单个介绍。

鼠标事件: 

mouseDoubleClickEvent()鼠标双击事件
mouseMoveEvent()鼠标移动事件
mousePressEvent()鼠标点击事件
MouseReleaseEvent()鼠标松开事件

例子:

一个矩形项,鼠标单机的话为红色,双击的话为蓝色,移动的话为绿色,松开的话为黄色,

默认为黑色

MyItem.h文件 

#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QMouseEvent>
class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) ;//鼠标移动事件
    void mousePressEvent(QGraphicsSceneMouseEvent *event) ;//鼠标点击事件
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) ;//鼠标松开事件
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) ;//鼠标双击事件
private:
    QColor color;//颜色
};

#endif // MYITEM_H

MyItem.cpp文件 

每次执行完之后要使用updata()更新一下数据,不然会卡顿。版本为(Qt5.9.9)

#include "myitem.h"

MyItem::MyItem()
{
    color=QColor(Qt::black);//默认为黑色

}
QRectF MyItem::boundingRect() const
{
    qreal penwidget=1;
    return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    painter->setBrush(color);
    painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) //鼠标移动事件
{
    color=QColor(Qt::green);
    update();
}
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) //鼠标点击事件
{
    setFocus();//设置焦点
    color=QColor(Qt::red);
    update();
}
void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) //鼠标松开事件
{
    color=QColor(Qt::yellow);
    update();
}
void MyItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) //鼠标双击事件
{
    color=QColor(Qt::blue);
    update();
}

main文件:

#include "widget.h"
#include "myitem.h"
#include <QApplication>
#include<QGraphicsScene>
#include<QGraphicsView>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene(-200,-200,400,400); //场景
    MyItem item; //项
    scene.addItem(&item);
    QGraphicsView view; //视图
    view.setScene(&scene);
    view.show();
    return a.exec();
}

运行结果:

         默认:                  单击:                     松开:                   双击:            鼠标移动:

 

 停靠事件:

hoverEnterEvent()悬停输入事件
hoverLeaveEvent()悬停离开事件
hoverMoveEvent()悬停移动事件

 默认情况下,不会接收悬停事件,需要使用setAcceptHoverEvents()开启接收悬停事件。

 例子:

默认为黑色,悬停离开为蓝色,悬停移动为绿色.

 MyItem.h文件 

#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QHoverEvent>
class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event) ;//悬停移动
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) ;//悬停进入
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) ;//悬停离开
private:
    QColor color;//颜色
};

#endif // MYITEM_H

MyItem.cpp

#include "myitem.h"

MyItem::MyItem()
{
    color=QColor(Qt::black);//默认为黑色
    setAcceptHoverEvents(true);//开启接收悬停

}
QRectF MyItem::boundingRect() const
{
    qreal penwidget=1;
    return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    painter->setBrush(color);
    painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) //悬停移动
{
    color=QColor(Qt::green);//绿色
    update();
}
void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) //悬停输入
{
}
void MyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) //悬停离开
{
    color=QColor(Qt::blue);//蓝色
    update();
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene(-200,-200,400,400);
    MyItem item;
    scene.addItem(&item);
    QGraphicsView view;
    view.setScene(&scene);
    view.show();
    return a.exec();
}

键盘事件:

keyPressEvent键盘点击
keyReleaseEvent键盘松开

使用键盘事件需要注意的事项:

  • 使用键盘事件的控件需要获取焦点,QGraphicsItem的话使用 setFocus()开启
  • 需要使用setFlag()函数开启标志。(不开启这个不能使用,是一个坑)

 enum QGraphicsItem::GraphicsItemFlag:(这几个是常见的,想要更加了解的话可以翻看官方文档)

QGraphicsItem::ItemIsMovable支持使用鼠标进行交互式移动。通过单击该项目然后拖动,该项目将与鼠标光标一起移动。
QGraphicsItem::ItemIsSelectable支持选择。启用此功能将启用 setSelected() 来切换项目的选择。
QGraphicsItem::ItemIsFocusable该项支持键盘输入焦点(即,它是输入项)。启用此标志将允许项目接受焦点
QGraphicsItem::ItemClipsToShape项目将剪辑到其自己的形状。该项目无法绘制或接收鼠标、平板电脑、拖放或将事件悬停在其形状之外。默认情况下处于禁用状态
QGraphicsItem::ItemClipsChildrenToShap项目将其所有后代的绘画剪辑成自己的形状。作为此项目的直接或间接子项的项不能在此项的形状之外绘制。
QGraphicsItem::ItemIgnoresTransformations项目忽略继承的变换,此标志可用于使文本标签项保持水平且不缩放,因此在转换视图时它们仍可读。

开启键盘的话,需要使用setFlag(QGraphicsItem::ItemIsFocusable)

例子:使用鼠标选取项,然后使用键盘的上下左右来移动矩形项,每次移动10

MyItem.h

#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QKeyEvent>
#include<QMouseEvent>
class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
    void keyPressEvent(QKeyEvent *event) ;//键盘点击
    void mousePressEvent(QGraphicsSceneMouseEvent *event);//鼠标点击事件
private:
    QColor color;//颜色
};

#endif // MYITEM_H

 MyItem.cpp

#include "myitem.h"

MyItem::MyItem()
{
    color=QColor(Qt::black);//默认为黑色
    this->setFlag(QGraphicsItem::ItemIsFocusable);//设置标志
}
QRectF MyItem::boundingRect() const
{
    qreal penwidget=1;
    return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    painter->setBrush(color);
    painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::keyPressEvent(QKeyEvent *event) //键盘点击
{
    if(event->key()==Qt::Key_Up)//向上
    {
        moveBy(0,-10);
    }
    else if(event->key()==Qt::Key_Down)//向下
    {
        moveBy(0,10);
    }
    else if(event->key()==Qt::Key_Left)//向左
    {
        moveBy(-10,0);
    }
    else if(event->key()==Qt::Key_Right)//向右
    {
        moveBy(10,0);
    }
    else{

    }
}
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    setFocus();//设置焦点
}

 

拖拽事件:

dragEnterEvent()拖动输入事件
dragLeaveEvent()拖拽离开事件
dragMoveEvent()拖动移动事件
dragEvent()拖拽事件

使用时需要注意的事项:

  • 默认不会开启拖拽,需要使用  setAcceptDrops(true)开启
  • 想要实现拖动控件的话还要开启 setFlag(QGraphicsItem::ItemIsMovable);

开启这两个函数即可实现拖拽控件:

//MyItem.h文件

#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QDropEvent>
class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
private:
    QColor color;//颜色
};

#endif // MYITEM_H



//MyItem.cpp文件

#include "myitem.h"

MyItem::MyItem()
{
    color=QColor(Qt::black);//默认为黑色
    this->setFlag(QGraphicsItem::ItemIsMovable);
    setAcceptDrops(true);//开启拖拽
}
QRectF MyItem::boundingRect() const
{
    qreal penwidget=1;
    return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    painter->setBrush(color);
    painter->drawRect(0,0,100,100);//画矩形
}

可以使用上面的几个事件实现你想要的结果,这里就不详细赘述。

上下文菜单事件:

通俗的讲就是: 你右键一个项,会弹出一些选择

contextMenuEvent()重新实现此事件处理程序以处理上下文菜单事件
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QMenu menu;//创建一个菜单
    QAction *removeAction = menu.addAction("Remove");//创建QAction创建行为 

    ...//可以有多个

    menu.exec(event->screenPos());//显示menu,设置在上下文菜单时鼠标光标在屏幕坐标中的位置

    connect();//使用connect()来连接对应的处理结果

}

例子:

MyItem.h

#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QDropEvent>
#include<QDebug>
class MyItem:public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;//上下文事件
private:
    QColor color;//颜色
};

#endif // MYITEM_H

MyItem.cpp

#include "myitem.h"

#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>

MyItem::MyItem()
{
    color=QColor(Qt::black);//默认为黑色
    this->setFlag(QGraphicsItem::ItemIsMovable);
    setAcceptDrops(true);//开启拖拽
}
QRectF MyItem::boundingRect() const
{
    qreal penwidget=1;
    return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    painter->setBrush(color);
    painter->drawRect(0,0,100,100);//画矩形
}

void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QMenu menu;
    QAction *A = menu.addAction("A");
    QAction *B = menu.addAction("B");
    QAction *C = menu.addAction("C");
    QAction *D = menu.addAction("D");
    
    QObject::connect(A,&QAction::triggered,[=]()
    {
        qDebug()<<"A";
    });
    QObject::connect(B,&QAction::triggered,[=]()
    {
        qDebug()<<"B";
    });
    QObject::connect(C,&QAction::triggered,[=]()
    {
        qDebug()<<"C";
    });
    QObject::connect(D,&QAction::triggered,[=]()
    {
        qDebug()<<"D";
    });

    menu.exec(event->screenPos());
}

main函数:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene(-200,-200,400,400);
    MyItem item;
    scene.addItem(&item);
    QGraphicsView view;
    view.setScene(&scene);
    view.show();
    return a.exec();
}

运行效果:

右键点击该控件:

分别点击ABCD,执行相应的输出:

 

参考文档:

QGraphicsItem Class | Qt Widgets 5.15.13

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/1668.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【二】一起算法---队列:STL queue、手写循环队列、双端队列和单调队列、优先队列

纸上得来终觉浅&#xff0c;绝知此事要躬行。大家好&#xff01;我是霜淮子&#xff0c;欢迎订阅我的专栏《算法系列》。 学习经典算法和经典代码&#xff0c;建立算法思维&#xff1b;大量编码让代码成为我们大脑的一部分。 ⭐️已更系列 1、基础数据结构 1.1、链表➡传送门 1…

【文心一言】什么是文心一言,如何获得内测和使用方法。

文心一言什么是文心一言怎么获得内测资格接下来就给大家展示一下文学创作商业文案创作数理逻辑推算中文理解多模态生成用python写一个九九乘法表写古诗前言&#xff1a; &#x1f3e0;个人主页&#xff1a;以山河作礼。 &#x1f4dd;​&#x1f4dd;:本文章是帮助大家了解文心…

24. linux系统基础

两个进程间想通讯&#xff0c;必须要通过内核&#xff0c;今天讲的信号其实本质也是讲进程间通讯的意思&#xff0c;那么你为什么可以在shell环境下&#xff0c;可以和一个进程发kill-9啊&#xff1f; shell是不是相当于一个进程&#xff1f;你自己运行的那个进程是不是也相当于…

HTTPS 加密协议

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录HTTPS"加密" 是什么HTTPS 的工作过程引入证书HTTPS http 安全层 (SSL) SSL 用来加密的协议&#xff0c;也叫 TLS …

GPT-4 API 接口调用及价格分析

GPT-4 API 接口调用及价格分析 15日凌晨&#xff0c;OpenAI发布了万众期待的GPT-4&#xff01;新模型支持多模态&#xff0c;具备强大的识图能力&#xff0c;并且推理能力和回答准确性显著提高。在各种专业和学术基准测试上的表现都媲美甚至超过人类。难怪OpenAI CEO Sam Altm…

HiveSql一天一个小技巧:利用array_contains()函数进行容器存在性计数问题分析

0 需求描述文章被引用关系数据表如下&#xff1a;idoid10203141526073其中id表示文章id,oid引用的文章&#xff0c;当oid为0时表示当前文章为原创文章&#xff0c;求原创文章被引用的次数。注意本题不能用关联的形式求解1 需求分析1.1 数据源准备with data as( select 1 as id,…

Springboot源代码总结

前言 编写微服务,巩固知识 文章目录 前言springboot原理springboot启动流程SpringBoot自动配置底层源码解析自动配置到底配了什么?自动配置类条件注解Starter机制@ConditionalOnMissingBeanSpringBoot启动过程源码解析构造SpringApplication对象SpringBoot完整的配置优先级s…

深入理解WebSocket协议

“ 一直以来对WebSocket仅停留在使用阶段&#xff0c;也没有深入理解其背后的原理。当看到 x x x was not upgraded to websocket&#xff0c;我是彻底蒙了&#xff0c;等我镇定下来&#xff0c;打开百度输入这行报错信息&#xff0c;随即看到的就是大家说的跨域&#xff0c;或…

SpringBoot帮你优雅的关闭WEB应用程序

Graceful shutdown 应用 Graceful shutdown说明 Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and servlet-based web applications. It occurs as part of closing the applica…

spring(七):事务操作

spring&#xff08;七&#xff09;&#xff1a;事务操作前言一、什么是事务二、事务四个特性&#xff08;ACID&#xff09;三、事务操作&#xff08;搭建事务操作环境&#xff09;四、事务操作&#xff08;Spring 事务管理介绍&#xff09;五、事务操作&#xff08;注解声明式事…

python学习——【第一弹】

前言 Python是一种跨平台的计算机程序设计语言&#xff0c;是ABC语言的替代品&#xff0c;属于面向对象的动态类型语言&#xff0c;最初被设计用于编写自动化脚本&#xff0c;随着版本的不断更新和语言新功能的添加&#xff0c;越来越多被用于独立的、大型项目的开发。 从这篇…

断言assert

assert作用&#xff1a;我们使用assert这个宏来调试代码语法&#xff1a;assert&#xff08;bool表达式&#xff09;如果表达式为false&#xff0c;会调用std::cout<<abort函数&#xff0c;弹出对话框&#xff0c;#include<iostream> #include<cassert> void…

学习 Python 之 Pygame 开发魂斗罗(八)

学习 Python 之 Pygame 开发魂斗罗&#xff08;八&#xff09;继续编写魂斗罗1. 创建敌人类2. 增加敌人移动和显示函数3. 敌人开火4. 修改主函数5. 产生敌人6. 使敌人移动继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗&#xff08;七&#xff09;中&#xff0…

uboot主目录下Makefile文件的分析,以及配置过程分析

主Makefile执行分析 uboot的编译过程 &#xff08;1&#xff09;配置 查看主Makefile文件下所支持的配置的板子&#xff0c;通过make x210_sd_config来实现编译前的配置 &#xff08;2&#xff09;编译 make直接编译&#xff0c;这个前提条件是主Makefile文件下指定了编译…

上手使用百度文心一言

3月16日&#xff0c;在距离新一代的GPT模型GPT-4发布还不足一天的时间内&#xff0c;百度便发布了对标ChatGPT的人工智能产品&#xff0c;名字叫&#xff1a;文心一言。成为国内首页发布该类型产品的公司。 那么&#xff0c;我们今天就来试一试百度的文心一言好不好用。 首先&a…

【ERNIE Bot】百度 | 文心一言初体验

文章目录一、前言二、文心一言介绍三、申请体验⌈文心一言⌋四、⌈文心一言⌋初体验1️⃣聊天对话能力2️⃣文案创作能力3️⃣文字转语音能力✨4️⃣AI绘画能力✨5️⃣数理推理能力6️⃣代码生成能力7️⃣使用技巧说明五、总结一、前言 ​ 最近有关人工智能的热门话题冲上热榜…

Java课程设计项目--音乐视频网站系统

一、功能介绍 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中人们对音乐方面的要求也在不断提高&#xff0c;听歌的人数更是不断增加&#xff0c;使得音乐网站的设计的开发成为必需而且紧迫的事情。音乐网站的设计主…

「操作系统」什么是用户态和内核态?为什么要区分

「操作系统」什么是用户态和内核态&#xff1f;为什么要区分 参考&鸣谢 从根上理解用户态与内核态 程序员阿星 并发编程&#xff08;二十六&#xff09;内核态和用户态 Lovely小猫 操作系统之内核态与用户态 fimm 文章目录「操作系统」什么是用户态和内核态&#xff1f;为什…

嵌入式硬件电路设计的基本技巧

目录 1 分模块 2 标注关键参数 3 电阻/电容/电感/磁珠的注释 4 可维修性 5 BOM表归一化 6 电源和地的符号 7 测试点 8 网络标号 9 容错性/兼容性 10 NC、NF 11 版本变更 12 悬空引脚 13 可扩展性 14 防呆 15 信号的流向 16 PCB走线建议 17 不使用\表示取反 不…

考研408每周一题(2019 41)

2019年(单链表&#xff09; 41.(13分)设线性表L(a1,a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存&#xff0c;链表中的结点定义如下&#xff1a; typedef struct node {int data;struct node *next; } NODE; 请设计一个空间复杂度为O(1)且时间上尽可能高效的算法&…