【PyQt学习篇 · ⑥】:QWidget - 事件
文章目录
- 事件消息
- 显示和关闭事件
- 移动事件
- 调整大小事件
- 鼠标事件
- 进入和离开事件
- 鼠标按下和释放事件
- 鼠标双击事件
- 鼠标按下移动事件
- 键盘事件
- 焦点事件
- 拖拽事件
- 绘制事件
- 改变事件
- 右键菜单
- 输入法
- 事件转发机制
- 案例一
- 案例二
- 案例三
事件消息
显示和关闭事件
-
showEvent(QShowEvent)方法:showEvent()方法在窗口即将显示时被调用。- 它的参数
QShowEvent可以提供一些有关显示事件的信息。 - 可以通过重写
showEvent()方法来执行一些在窗口显示前需要初始化的操作。
-
closeEvent(QCloseEvent)方法:closeEvent()方法在窗口即将关闭时被调用。- 它的参数
QCloseEvent可以提供一些有关关闭事件的信息。 - 可以通过重写
closeEvent()方法来执行一些在窗口关闭前需要处理的操作,例如保存数据或询问用户是否确认关闭窗口。
以下是一个使用showEvent()和closeEvent()的示例代码:
from PyQt5.QtWidgets import *
import sysclass MyWindow(QWidget):def __init__(self, parent=None):super().__init__(parent)def showEvent(self, QShowEvent):print('窗口被显示出来')def closeEvent(self, QCloseEvent):print('窗口被关闭')if __name__ == '__main__':app = QApplication(sys.argv)window = MyWindow()window.show()sys.exit(app.exec_())
运行结果:

移动事件
moveEvent(QMoveEvent)方法:
moveEvent()方法在窗口移动时被调用。- 它的参数
QMoveEvent提供了有关移动事件的详细信息,包括窗口的新位置。
以下是一个使用moveEvent()的示例代码:
def moveEvent(self, QMoveEvent):print("窗口被移动了")
运行结果:

调整大小事件
resizeEvent(QResizeEvent)方法:
resizeEvent()方法在窗口调整大小时被调用。- 它的参数
QResizeEvent提供了有关调整大小事件的详细信息,包括窗口的新大小。
以下是一个使用resizeEvent()的示例代码:
def resizeEvent(self, QResizeEvent):print('窗口大小被调整了')
运行结果:

鼠标事件
进入和离开事件
-
enterEvent(QEvent)方法:enterEvent()方法在鼠标进入窗口时被调用。- 它的参数
QEvent提供了有关进入事件的详细信息。 - 可以通过重写
enterEvent()方法来执行一些在鼠标进入窗口时需要的操作,例如更改鼠标的样式或显示一些提示信息。
-
leaveEvent(QEvent)方法:leaveEvent()方法在鼠标离开窗口时被调用。- 它的参数
QEvent提供了有关离开事件的详细信息。 - 可以通过重写
leaveEvent()方法来执行一些在鼠标离开窗口时需要的操作,例如清除鼠标的样式或隐藏提示信息。
以下是一个使用enterEvent()和leaveEvent()的示例代码:
# 鼠标进入控件时背景改为红色
def enterEvent(self, QEnterEvent):self.setStyleSheet("background-color: red;")# 鼠标离开控件时背景改为蓝色
def leaveEvent(self, QLeaveEvent):self.setStyleSheet("background-color: blue;")
运行结果:
如下图所示,左图为鼠标离开控件时,右图为进入控件时。

鼠标按下和释放事件
-
mousePressEvent(QMouseEvent)方法:mousePressEvent()方法在鼠标按下时被调用。- 它的参数
QMouseEvent提供了有关按下事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mousePressEvent()方法来执行一些在鼠标按下时需要的操作,例如捕获鼠标事件、拖拽操作或执行特定的函数。
-
mouseReleaseEvent(QMouseEvent)方法:mouseReleaseEvent()方法在鼠标释放时被调用。- 它的参数
QMouseEvent提供了有关释放事件的详细信息,例如鼠标的位置和释放的按钮。 - 可以通过重写
mouseReleaseEvent()方法来执行一些在鼠标释放时需要的操作,例如处理点击事件、完成拖拽操作或执行特定的函数。
以下是一个使用mousePressEvent()和mouseReleaseEvent()的示例:
def mousePressEvent(self, QMouseEvent):print('鼠标被按下')def mouseReleaseEvent(self, QMouseEvent):print('鼠标被松开')
运行结果:

鼠标双击事件
mouseDoubleClickEvent(QMouseEvent)方法:
mouseDoubleClickEvent()方法在鼠标双击时被调用。- 它的参数
QMouseEvent提供了有关双击事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mouseDoubleClickEvent()方法来执行一些在鼠标双击时需要的操作,例如打开新的窗口、执行特定函数或处理双击事件。
以下是一个使用mouseDoubleClickEvent(QMouseEvent)的示例:
def mouseDoubleClickEvent(self, QMouseEvent):print("鼠标双击了")
运行结果:

鼠标按下移动事件
mouseMoveEvent(QMouseEvent)方法:
mouseMoveEvent()方法在鼠标按下并移动时被调用。- 它的参数
QMouseEvent提供了有关鼠标移动事件的详细信息,例如鼠标的位置和按下的按钮。 - 可以通过重写
mouseMoveEvent()方法来执行一些在鼠标按下并移动时需要的操作,例如实现拖拽操作、更新鼠标位置信息或调整窗口大小。
在上一篇文章已介绍其使用方法,在这里就不赘述。
键盘事件
-
keyPressEvent(QKeyEvent)方法:keyPressEvent()方法在键盘按下时被调用。- 它的参数
QKeyEvent提供了有关按键事件的详细信息,例如按键的键码。 - 可以通过重写
keyPressEvent()方法来执行一些在按键按下时需要的操作,例如捕获按键事件并执行特定的函数或根据按键执行相应的操作。
-
keyReleaseEvent(QKeyEvent)方法:keyReleaseEvent()方法在键盘释放时被调用。- 它的参数
QKeyEvent提供了有关键盘释放事件的详细信息,例如释放的按键的键码。 - 可以通过重写
keyReleaseEvent()方法来执行一些在按键释放时需要的操作,例如根据按键的组合键执行操作或执行特定函数。
以下是一个使用keyPressEvent()和keyReleaseEvent()的示例代码:
def keyPressEvent(self, QKeyEvent):print('键盘被按下')def keyReleaseEvent(self, QKeyEvent):print('键盘松开')
运行结果:
按下两次空格后的结果。

焦点事件
-
focusInEvent(QFocusEvent)方法:focusInEvent()方法在控件获取焦点时被调用。- 可以通过重写
focusInEvent()方法来执行一些在控件获取焦点时需要的操作,例如更改控件的外观或更新与控件相关的属性。
-
focusOutEvent(QFocusEvent)方法:focusOutEvent()方法在控件失去焦点时被调用。- 可以通过重写
focusOutEvent()方法来执行一些在控件失去焦点时需要的操作,例如更新控件的状态或执行校验操作。
拖拽事件
在 PyQT 中,你可以通过在控件上实现一些拖拽事件处理函数来实现拖拽功能,其中包括以下几个 API:
-
dragEnterEvent(QDragEnterEvent)方法:dragEnterEvent()方法在拖拽对象进入控件时被调用。- 可以通过重写
dragEnterEvent()方法来指定控件支持的拖拽操作类型。
-
dragMoveEvent(QDragMoveEvent)方法:dragMoveEvent()方法在拖拽对象在控件内移动时被调用。- 可以通过重写
dragMoveEvent()方法来修改控件的外观以提供反馈。
-
dragLeaveEvent(QDragLeaveEvent)方法:dragLeaveEvent()方法在拖拽对象离开控件时被调用。- 可以通过重写
dragLeaveEvent()方法来恢复控件原来的外观。
-
dropEvent(QDropEvent)方法:dropEvent()方法在拖拽操作完成并释放鼠标时被调用。- 可以通过重写
dropEvent()方法来执行一些特定的功能,例如处理拖拽数据并更新控件状态。
绘制事件
在 PyQT 中,你可以通过在控件上实现一些绘制事件处理函数来实现控件的外观和样式的自定义,其中包括以下几个 API:
paintEvent(QPaintEvent) 方法:
paintEvent()方法在控件需要绘制时被调用。- 可以通过重写
paintEvent()方法来绘制自定义的控件外观和样式。
改变事件
changeEvent(QEvent) 方法:
changeEvent()方法在控件的状态发生改变时被调用。- 它的参数
QEvent提供了有关状态变化的详细信息,例如当前输入法的变化、窗口状态的变化等。 - 可以通过重写
changeEvent()方法来响应这些状态变化,并且更新控件的外观和样式。
右键菜单
contextMenuEvent(QContextMenuEvent) 方法:
contextMenuEvent()方法在右键单击控件时被调用。- 它的参数
QContextMenuEvent提供了有关右键单击事件的详细信息。 - 可以通过重写
contextMenuEvent()方法来显示一个自定义的右键菜单。
输入法
inputMethodEvent(QInputMethodEvent) 方法:
inputMethodEvent()方法在输入法发生变化时被调用。- 它的参数
QInputMethodEvent提供了有关输入法变化的详细信息。 - 可以通过重写
inputMethodEvent()方法来响应输入法变化,并更新控件的外观和样式。
事件转发机制
在 PyQt 中,事件转发(Event Forwarding)机制允许控件将接收到的事件传递给其他控件进行处理。这种机制可以使用 event() 方法来实现。
当一个控件接收到一个事件时,它会首先调用自己的 event() 方法进行事件处理。如果控件不处理该事件,或者希望将事件传递给其他控件进行处理,它可以调用 super().event(event) 将事件转发给父类控件来处理。
以下为事件转发的示例:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sysclass Window(QWidget):def mousePressEvent(self, QMouseEvent):print('顶层窗口被按下')class MidWindow(QWidget):def mousePressEvent(self, QMouseEvent):print('中间控件被按下')class Label(QLabel):def mousePressEvent(self, QMouseEvent):print('标签控件被按下')if __name__ == '__main__':app = QApplication(sys.argv)window = Window()window.setWindowTitle('事件转发机制')window.resize(500, 500)mid_window = MidWindow(window)mid_window.resize(300, 300)mid_window.setAttribute(Qt.WA_StyledBackground, True) # 让样式生效mid_window.setStyleSheet('background-color: yellow;')label = Label(mid_window)label.setText('我是标签')label.move(100, 100)label.setStyleSheet('background-color: red;')window.show()sys.exit(app.exec_())
运行结果:

当注释掉以下代码:
class Label(QLabel):pass#def mousePressEvent(self, QMouseEvent):#print('标签控件被按下')
在标签位置按下鼠标时,打印“中间控件被按下”,说明鼠标按下事件分发到了父类,即MidWindow。
运行结果:

案例一
案例一:创建一个窗口包含一个标签。
要求:鼠标进入标签时,展示“欢迎光临”;鼠标离开标签时,展示“谢谢惠顾”。
案例一的代码:
from PyQt5.QtWidgets import *
import sysclass Label(QLabel):def enterEvent(self, QEnterEvent):self.setText('欢迎光临')def leaveEvent(self, QLeaveEvent):self.setText('谢谢惠顾')if __name__ == '__main__':app = QApplication(sys.argv)window = QWidget()window.setWindowTitle('案例一')window.resize(500, 500)label = Label(window)label.setGeometry(100, 100, 300, 300)label.setStyleSheet('background-color: cyan;')window.show()sys.exit(app.exec_())
运行结果:

案例二
案例二:创建一个窗口,监听用户按键。
要求:
- 监听用户输入Tab键
- 监听用户输入Ctrl+S组合键
- 监听用户输入Ctrl+Shift+A
补充:
修饰键:
Qt.NoModifier:没有修饰键Qt.ShiftModifier:Shift键被按下Qt.ControlModifier:Ctrl键被按下Qt.AltModifier:Alt键被按下- ……
- 多个修饰键之间使用或运算
普通键:
Qt.Key_xxx
以下为案例二的代码:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sysclass Label(QLabel):def __init__(self, parent=None):super().__init__(parent)def keyPressEvent(self, QKeyEvent):if QKeyEvent.key() == Qt.Key_Tab:self.setText('按下Tab键')if QKeyEvent.modifiers() == Qt.ControlModifier and QKeyEvent.key() == Qt.Key_S:self.setText('ctrl + s 被点击')if QKeyEvent.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and QKeyEvent.key() == Qt.Key_A:self.setText('ctrl + Shift + A 被按下')if __name__ == '__main__':app = QApplication(sys.argv)window = QWidget()window.resize(500, 500)window.setWindowTitle('案例二')label = Label(window)label.resize(300, 300)label.move(100, 100)label.setContentsMargins(50, 0, 0, 0)label.setStyleSheet('background-color: cyan;')label.grabKeyboard() # 捕获键盘window.show()
运行结果:

案例三
案例三:创建一个窗口,用户区支持脱宅。
要求:鼠标点击了用户区拖拽也可以移动窗口。
分析:
- 先获取鼠标按下左键时的位置:mouse_x = evt.globalX()、mouse_y = evt.globalY()
- 再获取窗口的坐上角的位置:origin_x = x()、origin_y = y()
- 鼠标移动的距离:move_x = evt.globalX()-mouse_x、move_y=evt.globalY()-mouse_y
- 窗口该移动的距离:dest_x = origin_x + move_x、dest_y = origin_y + move_y

以下为案例三的代码:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sysclass MyWindow(QWidget):def __init__(self, parent=None):super().__init__(parent)self.move_Flag = Falsedef mousePressEvent(self, QMouseEvent):if QMouseEvent.button() == Qt.LeftButton: # 判断是左键按下self.move_Flag = True# 鼠标第一次按下时的位置self.mouse_x = QMouseEvent.globalX()self.mouse_y = QMouseEvent.globalY()# 窗口左上角的坐标self.origin_x = self.x()self.origin_y = self.y()def mouseMoveEvent(self, QMouseEvent):if self.move_Flag:# 计算移动量move_x = QMouseEvent.globalX() - self.mouse_xmove_y = QMouseEvent.globalY() - self.mouse_y# 移动的位置dest_x = self.origin_x + move_xdest_y = self.origin_y + move_yself.move(dest_x, dest_y)def mouseReleaseEvent(self, QMouseEvent):self.move_Flage = Falseif __name__ == '__main__':app = QApplication(sys.argv)window = MyWindow()window.resize(300, 300)window.setWindowTitle('案例三')window.show()sys.exit(app.exec_())
相关文章:
【PyQt学习篇 · ⑥】:QWidget - 事件
文章目录 事件消息显示和关闭事件移动事件调整大小事件鼠标事件进入和离开事件鼠标按下和释放事件鼠标双击事件鼠标按下移动事件 键盘事件焦点事件拖拽事件绘制事件改变事件右键菜单输入法 事件转发机制案例一案例二案例三 事件消息 显示和关闭事件 showEvent(QShowEvent)方法…...
Vue、jquery和angular之间区别
aVue、jquery、angular之间区别 angular与jquery区别angular和Vue angular与jquery区别 三个版本的输入数据绑定,都是单页面应用。 Angular <body ng-app><input type"text" ng-model"name"><p>{{name}}</p></body…...
MATLAB算法实战应用案例精讲-【图像处理】机器视觉(基础篇)(六)
目录 前言 几个高频面试题目 工业相机与普通相机的差别 一、 工业相机与普通相机的区别...
硬件知识积累 RS232 接口
1. RS232 是什么 RS-232标准接口(又称EIA RS-232)是常用的串行通信接口标准之一,它是由美国电子工业协会(Electronic Industry Association,EIA)联合贝尔系统公司、调制解调器厂家及计算机终端生产厂家于1970年共同制定࿰…...
机器人入门(四)—— 创建你的第一个虚拟小车
机器人入门(四)—— 创建你的第一个虚拟小车 一、小车建立过程1.1 dd_robot.urdf —— 建立身体1.2 dd_robot2.urdf —— 添加轮子1.3 dd_robot3.urdf —— 添加万向轮1.4 dd_robot4.urdf —— 添加颜色1.5 dd_robot5.urdf —— 添加碰撞检测(Collision …...
部署K8S
防火强的初始化: [rootk8s-node-12 ~]# systemctl stop firewalld NetworkManager [rootk8s-node-12 ~]# systemctl disable firewalld NetworkManager Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service. Removed symlink /et…...
[NSSCTF 2nd] web刷题记录
文章目录 php签到MyBox非预期解预期解 php签到 源代码 <?phpfunction waf($filename){$black_list array("ph", "htaccess", "ini");$ext pathinfo($filename, PATHINFO_EXTENSION);foreach ($black_list as $value) {if (stristr($ext, …...
MyBatis获取参数值的两种方式(重点)
文章目录 简介单个字面量类型的参数多个字面量类型的参数map集合类型的参数实体类类型的参数使用Param标识参数总结 简介 MyBatis获取参数值的两种方式:${}和#{}${}的本质就是字符串拼接,#{}的本质就是占位符赋值${}使用字符串拼接的方式拼接sql&#x…...
Cesium弹窗可随地图移动
目录 项目地址实现效果实现方法 项目地址 https://github.com/zhengjie9510/webgis-demo 实现效果 实现方法 handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) handler.setInputAction((click) > {if (listener) {listener()listener undefinedthis.v…...
MySQL WITH AS及递归查询
MySQL WITH AS及递归查询 WITH AS 官网:WITH 是 SQL 中的一个关键字,用于创建临时表达式(也称为 Common Table Expression,CTE),它允许你在一个查询中临时定义一个表达式,然后在后续的查询中引…...
Harbor私有镜像仓库搭建
本文基于:https://zhuanlan.zhihu.com/p/143779176 1.环境准备 IP:192.168.10.136/24 操作系统:centos7 2.安装Docker、Docker-compose 2.1安装Docker-CE $ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.re…...
线段树 区间赋值 + 区间加减 + 求区间最值
线段树好题:P1253 扶苏的问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 区间赋值 区间加减 求区间最大。 对于区间赋值和区间加减来说,需要两个懒标记,一个表示赋值cover,一个表示加减add。 区间赋值的优先级大于区间加…...
大模型之十九-对话机器人
大语言模型的最早应用是Chatbot,其实我最早接触语义理解在2014年,2014年做智能音箱的时候,那时也是国内第一批做智能音箱的,在现在看起来当时的智能音箱比较傻,很多问题无法回答,长下文效果也不好ÿ…...
『力扣刷题本』:删除排序链表中的重复元素
一、题目 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 示例 1: 输入:head [1,1,2] 输出:[1,2]示例 2: 输入:head [1,1,2,3,3] 输出&am…...
Android S从桌面点击图标启动APP流程 (六)
系列文章 Android S从桌面点击图标启动APP流程 (一)Android S从桌面点击图标启动APP流程 (二) Android S从桌面点击图标启动APP流程 (三) Android S从桌面点击图标启动APP流程 (四) Android S从桌面点击图标启动APP流程 (五) Android 12的源码链接: android 1…...
Java I/O (输入/输出)
1.流的概念 流是一种有序的数据序列,根据操作类型,可以分为输入流和输出流两种。I/O流(输入输出)提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。 1.1 输入流: 程序从指向源的输入流中读…...
nodejs+vue食力派网上订餐系统-计算机毕业设计
采用当前流行的B/S模式以及3层架构的设计思想通过 技术来开发此系统的目的是建立一个配合网络环境的食力派网上订餐系统,这样可以有效地解决食力派网上订餐管理信息混乱的局面。 本设计旨在提高顾客就餐效率、优化餐厅管理、提高订单准确性和客户的满意度。本系统采…...
【计算机视觉】对极几何
文章目录 一、极线约束(Epipolar Constraint)二、相机标定过的情况三、相机没有标定过的情况四、八点算法(eight-point algorithm) 我的《计算机视觉》系列参考UC Berkeley的CS180课程,PPT可以在课程主页看到。 在上一…...
强大易于编辑的流程图组织图绘制工具draw.io Mac苹果中文版
draw.io可以绘制多种类型的图表,包括但不限于流程图、组织结构图、网络图、UML图、电气工程图等。draw.io提供了丰富的图形元素和编辑功能,使用户能够轻松地创建和编辑各种复杂的图表。同时,该软件还支持多种导出格式,方便用户在不…...
c# .net6 在线条码打印基于
条码打印基于:BarTender、ORM EF架构 UI展示: 主页代码: using NPOI.OpenXmlFormats.Spreadsheet; using ServerSide.Models; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawi…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
