PyQt5中信号与槽可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个控件进行使用的,比如一个按钮,当我们使用按钮时,只关心clicked信号,至于这个按钮如何接受并处里鼠标点击事件,然后在发射这个信号,则不关心,但是如果要重载一个按钮,这时候就要关心了,比如可以改变它的行为:在鼠标按下时触发clicked信号,而不是释放时
PyQt5常见事件类型
pyqt是对Qt的封装,qt程序是事件驱动的,它的每个动作都有幕后某个事件所触发,Qt事件类型有很多,常见的如下
键盘事件:按键的按下与松开
鼠标事件:鼠标指针的移动,鼠标按键的按下与松开
拖放事件:用鼠标进行拖放
滚轮事件:鼠标滚轮滚动
绘屏事件:重绘制屏幕的某些部分
定时事件:定时器到时
焦点事件:键盘焦点移动
进入和离开事件:鼠标指针移入Widget内,或者移出
移动事件:Widget的位置改变
大小改变事件:widget的大小改变
显示和隐藏事件:widget显示与隐藏
窗口事件:窗口是否为当前窗口
还有一些常见的qt事件,比如Socket事件,剪切板事件,字体改变事件,布局改变事件
使用事件处理的方法
pyqt提供如下5中事件处理和过滤的方法(有弱到强),其中只有前两种方法使用最频繁
1 、重新实现事件函数
比如mousePressEvent(),keyPressEvent(),paintEvent(),这是最常规的事件处理方法
2 、重新实现QObject.event()
一般用在pyqt没有提供该事件的处理函数的情况下,即增加新事件时
3 、安装事件过滤器
如果对QObject调用installEventFilter,则相当于为这个QObject安装了一个事件过滤器,对于QObject的全部事件来说,它们都会先传递到事件过滤函数eventFilter中,在这个函数中,我们可以抛弃或者修改这些事件,比如对自己感兴趣的事件使用自定义的处理机制,对其他事件采用默认的事件处理机制,由于这中方法会调用installEventFilter的所有QObject的事件进行过滤,因此如果要过滤的事件比较多,则会降低程序的性能
4 、在QApplication中安装事件过滤器
这种方法比上一种更强大,QApplication的事件过滤器将捕获所有的QObject事件,而且第一个获得该事件,也就是说,在将事件发送给其他任何一个事件过滤器之前,都会发送给QApplication的事件过滤器
5 、重新实现QApplication的notify()方法
pyqt使用notify来分发事件,要想在任何事件处理器之前捕获事件,唯一的方法就是重新实现QApplication的notify(),在实践中,在调试才会用这中方法
PyQt5信号与槽事件处理经典案例
import sys
from PyQt5.QtCore import (QEvent, QTimer, Qt)
from PyQt5.QtWidgets import (QApplication, QMenu, QWidget)
from PyQt5.QtGui import QPainter
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
#初始化数据
#鼠标双击False
self.justDoubleClicked = False
#按键,输出文本,提示消息为空
self.key = ""
self.text = ""
self.message = ""
#设置窗口初始大小与位置
self.resize(400, 300)
self.move(100, 100)
#设置标题
self.setWindowTitle("Events")
#定时器1秒后执行槽函数
QTimer.singleShot(1000, self.giveHelp)
# 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。
def giveHelp(self):
self.text = "请点击这里触发追踪鼠标功能"
# 重绘事件,也就是触发paintEvent函数。
self.update()
'''重新实现关闭事件'''
def closeEvent(self, event):
print("Closed")
'''重新实现上下文菜单事件'''
def contextMenuEvent(self, event):
#实例化菜单,添加子菜单one two并附加快捷键功能,关联槽函数
menu = QMenu(self)
oneAction = menu.addAction("&One")
twoAction = menu.addAction("&Two")
oneAction.triggered.connect(self.one)
twoAction.triggered.connect(self.two)
#如果message为空,执行
if not self.message:
#在菜单中添加一条分割线
menu.addSeparator()
#添加自菜单three,关联槽函数
threeAction = menu.addAction("Thre&e")
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()
'