【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…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
