详解PyQt5 事件处理机制
作者:SongYuLong的博客 发布时间:2023-04-06 00:09:34
标签:PyQt5,事件,机制
PyQt5 事件处理机制
PyQt为事件处理提供了两种机制:高级的信号与槽机制,以及低级的事件处理机制。信号与槽可以说是对事件处理机制的高级封装。
常见事件类型:
键盘事件:按键按下和松开。
鼠标事件:鼠标指针移动,鼠标按下和松开。
拖放事件:用鼠标进行拖放。
滚轮事件:鼠标滚轮滚动。
绘屏事件:重绘屏幕的某些部分。
定时事件:定时器到时。
焦点事件:键盘焦点移动。
进入/离开事件:鼠标指针移入Widget内,或者移出。
移动事件:Widget的位置改变。
大小改变事件:Widget的大小改变。
显示/隐藏事件:Widget显示和隐藏。
窗口事件:窗口是否为当前窗口。
PyQt提供了如下5种事件处理和过滤方法(有弱到强):
重新实现事件函数,比如mousePressEvent(),keyPressEvent()等等。
重新实现QObject.event()。
安装时间过滤器。
在QApplication中安装事件过滤器。
重新实现QAppliction的notifiy()方法。
import sys
from PyQt5.QtWidgets import (QApplication, QMenu, QWidget)
from PyQt5.QtCore import (QEvent, QTimer, Qt)
from PyQt5.QtGui import QPainter
class MyEventDemoWindow(QWidget):
def __init__(self, parent=None):
super(MyEventDemoWindow, self).__init__(parent)
self.justDoubleClikcked = False
self.key = ""
self.text = ""
self.message = ""
self.resize(400, 300)
self.move(100, 100)
self.setWindowTitle("Events Demo 1")
QTimer.singleShot(1000, self.giveHelp)
def giveHelp(self):
self.text = "请点击这里触发追踪鼠标功能"
self.update() # 重绘事件,也就是除非paintEvent函数
# 重新实现关闭事件
def closeEvent(self, event):
print("Closed")
# 重新实现上下文菜单事件
def contextMenuEvent(self, event):
menu = QMenu(self)
oneAction = menu.addAction("&One")
twoAction = menu.addAction("&Two")
oneAction.triggered.connect(self.one)
twoAction.triggered.connect(self.two)
if not self.message:
menu.addSeparator()
threeAction = menu.addAction("&Three")
threeAction.triggered.connect(self.three)
menu.exec_(event.globalPos())
def one(self):
self.message = "Menu Option One"
self.update()
def two(self):
self.message = "Menu Option Two"
self.update()
def three(self):
self.message = "Menu Option Three"
self.update()
'''重新实现绘制事件'''
def paintEvent(self, event):
text = self.text
i = text.find("\n\n")
if i >= 0:
text = text[0:i]
if self.key:
text += "\n\n你按下了:{0}".format(self.key)
painter = QPainter(self)
painter.setRenderHint(QPainter.TextAntialiasing)
painter.drawText(self.rect(), Qt.AlignCenter, text) # 绘制文本
if self.message:
painter.drawText(self.rect(), Qt.AlignBottom | Qt.AlignHCenter, self.message)
QTimer.singleShot(5000, self.clearMessage)
QTimer.singleShot(5000, self.update)
# 清空文本信息槽函数
def clearMessage(self):
self.message = ""
# 重新实现调整窗口大小事件
def resizeEvent(self, event):
self.text = "调整窗口大小为: QSize({0}, {1})".format(event.size().width(), event.size().height())
self.update()
# 重新实现鼠标释放事件
def mouseReleaseEvent(self, event) -> None:
if self.justDoubleClikcked:
self.justDoubleClikcked = False
else :
self.setMouseTracking(not self.hasMouseTracking()) # 单击鼠标
if self.hasMouseTracking():
self.text = "你释放了鼠标 开启鼠标跟踪功能.\n\n" + \
"请移动鼠标\n\n" + \
"单击鼠标可以关闭这个功能"
else:
self.text = "你释放了鼠标 关闭鼠标跟踪功能" + \
"单击鼠标可以开启这个功能"
self.update()
'''重新实现鼠标移动事件'''
def mouseMoveEvent(self, event):
if not self.justDoubleClikcked:
globalPos = self.mapToGlobal(event.pos())# 将窗口坐标转换为屏幕坐标
self.text = """鼠标位置:
窗口坐标为:QPoint({0}, {1})
屏幕坐标为:QPoint({2}, {3})""".format(event.pos().x(), event.pos().y(), globalPos.x(), globalPos.y())
self.update()
'''重新实现鼠标双击事件'''
def mouseDoubleClickEvent(self, event):
self.justDoubleClikcked = True
self.text = "你双击了鼠标"
self.update()
def mousePressEvent(self, event):
self.text = "你按下了鼠标"
self.update()
def keyPressEvent(self, event):
self.text = "你按下了按键"
self.key = ""
if event.key() == Qt.Key_Home:
self.key = "Home"
elif event.key() == Qt.Key_End:
self.key = "End"
elif event.key() == Qt.Key_PageUp:
if event.modifiers() & Qt.ControlModifier:
self.key = "Ctrl + Page Up"
else:
self.key = "Page Up"
elif event.key() == Qt.Key_PageDown:
if event.modifiers() & Qt.ControlModifier:
self.key = "Ctrl + Key_PageDown"
else:
self.key = "Key_PageDown"
elif Qt.Key_A <= event.key() <= Qt.Key_Z:
if event.modifiers() & Qt.ShiftModifier:
self.key = "Shift+"
self.key += event.text()
if self.key:
self.key = self.key
self.update()
else:
QWidget.keyPressEvent(self, event)
def keyReleaseEvent(self, event):
self.text = "你释放了按键"
self.update()
'''重新实现event,捕获Tab键'''
def event(self, event):
if (event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab):
self.key = "在event() 中捕获Tab键"
self.update()
return True # 返回True表示本次事件已经执行处理
else:
return QWidget.event(self, event) # 继续处理事件
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MyEventDemoWindow()
win.show()
sys.exit(app.exec_())
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class EventFilter(QDialog):
def __init__(self, parent=None):
super(EventFilter, self).__init__(parent)
self.setWindowTitle("事件过滤器")
self.label1 = QLabel("请点击")
self.label2 = QLabel("请点击")
self.label3 = QLabel("请点击")
self.LabelState = QLabel("test")
self.image1 = QImage("pyqt5/images/cartoon1.ico")
self.image2 = QImage("pyqt5/images/cartoon1.ico")
self.image3 = QImage("pyqt5/images/cartoon1.ico")
self.width = 600
self.height = 300
self.resize(self.width, self.height)
self.label1.installEventFilter(self)
self.label2.installEventFilter(self)
self.label3.installEventFilter(self)
mainLayout = QGridLayout(self)
mainLayout.addWidget(self.label1, 500, 0)
mainLayout.addWidget(self.label2, 500, 1)
mainLayout.addWidget(self.label3, 500, 2)
mainLayout.addWidget(self.LabelState, 600, 1)
self.setLayout(mainLayout)
def eventFilter(self, watched, event):
# print(type(watched))
if watched == self.label1: # 只对label1的点击事件进行过滤,重写其行为,其它事件会被忽略
if event.type() == QEvent.MouseButtonPress: # 这里对鼠标按下事件进行过滤,重写其行为
mouseEvent = QMouseEvent(event)
if mouseEvent.buttons() == Qt.LeftButton:
self.LabelState.setText("按下鼠标左键")
elif mouseEvent.buttons() == Qt.MidButton:
self.LabelState.setText("按下鼠标中键")
elif mouseEvent.buttons() == Qt.RightButton:
self.LabelState.setText("按下鼠标右键")
'''转换图片大小'''
transform = QTransform()
transform.scale(0.5, 0.5)
tmp = self.image1.transformed(transform)
self.label1.setPixmap(QPixmap.fromImage(tmp))
if event.type() == QEvent.MouseButtonRelease: # 这里对鼠标释放事件进行过滤,重写其行为
self.LabelState.setText("释放鼠标按键")
self.label1.setPixmap(QPixmap.fromImage(self.image1))
return QDialog.eventFilter(self, watched, event) # 对于其它情况,会返回系统默认的事件处理方法
if __name__ == "__main__":
app = QApplication(sys.argv)
win = EventFilter()
win.show()
app.exec_()
来源:https://blog.csdn.net/songyulong8888/article/details/128104547


猜你喜欢
- 目录1. 什么是竞态2. 如何消除竞态3. Go 提供的并发工具3.1 互斥锁3.2 读写互斥锁3.3 Once3.4 竞态检测器4. 小结
- 在mysql文档中,mysql变量可分为两大类,即系统变量和用户变量。但根据实际应用又被细化为四种类型,即局部变量、用户变量、会话变量和全局
- 出现这个问题的原因不是'/xxx.frm'这个文件不见了,而是这些文件的权限(应该要是mysql)不知道为什么变成了root
- drop procedure sp_name//在此之前,小编给大家讲述过MYSQL语法的基本知识,本篇内容,小编通过下面的一个实例,给读者
- 本文实例讲述了Python3.5装饰器原理及应用。分享给大家供大家参考,具体如下:1、装饰器:(1)本质:装饰器的本质是函数,其基本语法都是
- 这几天正在追剧,原名《大秦帝国之天下》的《大秦赋》,看着看着又想把前几部刷一遍了,但第一部《裂变》自己没有高清资源,搜了一波发现yout
- Numba是Python的即时编译器,在使用NumPy数组和函数以及循环的代码上效果最佳。使用Numba的最常见方法是通过其装饰器集合,这些
- ping的原理是发送一个ICMP请求包,然后根据目的地址的应答包来判断是否能够和这个主机进行通信。我们使用python实现,借助于scapy
- 在利用torch.max函数和F.Ssoftmax函数时,对应该设置什么维度,总是有点懵,遂总结一下:首先看看二维tensor的函数的例子:
- 本文实例讲述了GO语言实现列出目录和遍历目录的方法。分享给大家供大家参考。具体如下:GO语言获取目录列表用 ioutil.ReadDir()
- 如下所示:# -*- coding=utf-8 -*- import urllib2import socketimport timeurls
- python列表变量可以存储一个元素,而列表是一个大容器,可以存储N多个元素,程序可以方便的对这些数据进行整体操作(可以存储多个不同的数据类
- JavaScript中的64位加密及解密的两个方法。function base64Encode(text){if (/(
- 在开发和调试基于XML的应用的时候,程序员往往为找不到合适的快速桌面XPATH测试软件发愁。诚然,市面上有成套的XML编辑软件,但是它们往往
- 一、简单配置,获取单个网页上的内容。(1)创建scrapy项目scrapy startproject getblog(2)编辑
- 一、Tensorlow结构import tensorflow as tfimport numpy as np#创建数据x_data = np
- 第一类:对于下面的这些option的可选参数,value应该被设置一个bool类型的值:选项可选value值备注CURLOPT_AUTORE
- 前言为了保证数据的一致完整性,任何一个数据库都存在锁定机制。锁定机制的优劣直接应想到一个数据库系统的并发处理能力和性能,所以锁定机制的实现也
- 本文实例讲述了PHP基于rabbitmq操作类的生产者和消费者功能。分享给大家供大家参考,具体如下:注意事项:1、accept.php消费者
- 最近要做一个微信平台的投票活动,需要在关注公众号之后才能参与投票,那么,如何判断用户是否关注了公众号呢?第一想法是,通过获取公众号的关注列表