图形视图框架 事件处理(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
相关文章:

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

PTA第六章作业详解
🚀write in front🚀 📝个人主页:认真写博客的夏目浅石. 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:夏目的作业 💬总结:希望你看完之后&am…...

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

FPGA可以转IC设计吗?需要学习哪些技能?
曾经在知乎上看到一个回答“入职做FPGA,后续是否还可以转数字IC设计?” 从下面图内薪资就可以对比出来,对比FPGA的行业薪资水平,IC行业中的一些基础性岗位薪资比很多FPGA大多数岗位薪资都要高。 除了薪资之外更多FPGA转IC设计的有…...

初探Gradle
目录一.概述二.优点三.安装与配置1. 官网下载2. 配置环境变量3. 检验4. 配置国内镜像(可选)5. IDEA配置三.工程结构四.生命周期1.Initialization阶段2.Configuration阶段3.Execution阶段五.Task六.常用任务指令七.引入依赖1.本地依赖2.项目依赖3.直接依赖八.依赖类型九.插件十.…...
国产数据库介绍
人大金仓 Kingbase 北京人大金仓信息技术股份有限公司于1999年由中共人民大学专家创立,自成立以来,始终立足自主研发,专注数据管理领域,先后承担了国家“863”、“核高基”等重大专项,研发出了具有国际先进水平的大型…...
Java OpenJudge-test3
目录 1:明明的随机数 2:合影效果 3:不重复的单词 4:和为给定数 5:字符串数组排序问题 6:字符串排序 7:求序列中的众数 1:明明的随机数 总时间限制: 1000ms 内存限制: 65536kB 描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性ÿ…...

蓝桥杯刷题冲刺 | 倒计时22天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.选数异或2.特殊年份1.选数异或 题目 链接: 选数异或 - 蓝桥云课 (lanqiao.cn) 给定…...

入行 5年,跳槽 3次,我终于摸透了软件测试这行(来自过来人的忠告)
目录 前言 第一年 第二年 第三年 第四年 作为过来人的一些忠告 前言 最近几年行业在如火如荼的发展壮大,以及其他传统公司都需要大批量的软件测试人员,但是20年的疫情导致大规模裁员,让人觉得行业寒冬已来,软件测试人员的职…...
开源时序数据库学习
计划学习使用QuestDB解决大数据日志存储场景。以下是常见引擎比较 比较项目 InfluxDB TimescaleDB OpenTSDB QuestDB 数据模型 Key-Value Relational Key-Value Relational 存储引擎 自主开发的TSI PostgreSQL扩展程序 Apache HBase 自主开发 查询语言 InfluxQ…...

字节测试工程师悄悄告诉我的软件测试、测试开发常用的测试策略与测试手段
目录 前言 测试策略的关注重点 测试策略主要内容 总体测试策略 初级版本测试策略 跟踪测试执行 版本质量评估 后续版本测试策略 发布质量评估 测试手段 前言 测试策略是指在特定环境约束之下,描述软件开发周期中关于测试原则、方法、方式的纲要ÿ…...
我常用的shell 进制转换工具
一、进制的一些基础知识 1. 二进制(binary) 二进制的取值是0和1; 前缀是 0b 2. 八进制(Octal) 八进制的取值是0-7;前缀是 O 3. 十进制(decimal) 十进制的取值是0-9;没有前缀 …...

手写vue(二)响应式实现
名词解释:vm:指Vue实例一、目标效果vue定义(1)新建vm时,可以通过一个data对象,或者data函数,其属性可以通过vm直接访问,而data对象可以通过vm._data获取(2)修…...
mysql数据库常问面试题
1、NOW()和CURRENT_DATE()有什么区别? NOW()命令用于显示当前年份,月份,日期,小时,分钟和秒。 CURRENT_DATE()仅显示当前年份,月份和日期。 2、CHAR和VARCHAR的区别? (1)…...

AI风暴 :文心一言 VS GPT-4
💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 文心一言 VS GPT-4 文心一言:知识增强大语言模型百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动&#…...

VR全景城市,用720全景树立城市形象,打造3D可视化智慧城市
随着城市化进程的加速,城市之间的竞争也日益激烈。城市管理者们需要寻求新的方式来提升城市的品牌形象和吸引力。在这个过程中,VR全景营销为城市提供了一种全新的营销手段,可以帮助提升城市的价值和吸引力。一、城市宣传新方式VR全景营销是一…...

javaweb窗口服务人员分析评价系统ssh
A)后台管理员模块:通过该功能模块,管理员可以修改自己的密码,并对管理员进行添加和删除操作。 B)注册用户模块:通过该功能模块,管理员可以查看注册用户的基本信息,对存在问题的用户进…...

树莓派Pico W无线开发板UDP协议MicroPython网络编程实践
树莓派Pico W无线开发板(简称Pico W)是树莓派基金会于2022年6月底推出的搭载无线通信芯片的树莓派Pico开发板。本文在介绍树莓派Pico W无线开发板接口信号和TCP/IP和UDP通信协议基础上,给出Pico W无线开发板的UDP协议MicroPython网络编程实例…...

跨域解决方案
跨域解决方案 1.跨域基本介绍 文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS 跨域问题是什么? 一句话:跨域指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 javascr…...
springboot的统一处理
在处理网络请求时,有一部分功能是需要抽出来统一处理的,与业务隔开。 登录校验 可以利用spring mvc的拦截器Interceptor,实现HandlerInterceptor接口即可。实现该接口后,会在把请求发给Controller之前进行拦截处理。 拦截器的实…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...