PyQt5事件处理
阅读原文时间:2023年07月10日阅读:3

事件介绍

事件的处理机制非常的复杂,属于PyQt底层的事,不必我们关心,学会使用就行。如果说事件是用来创建窗口,那么信号与槽就是用来对这个控件进行处理。事件属于低级的处理方式,信号与槽是高级的处理方式,一般信号与槽处理不了的问题,再使用事件处理。信号与槽功能强大使用简单但是不能解决所有的问题,事件使用麻烦但是可以处理全部的问题。事件的处理主要是重载类方法,信号与槽的处理主要是绑定、发送以及处理。

事件

  1. 重写mousePressEvent,keyPressEvent,paintEvent等方法,最常用(控件级)

  2. 重写QObject.event方法,一般在PyQt没有提供该事件的处理方法时使用(控件级)

  3. 安装事件过滤器:如果对QObject调用installEventFilter,相当于对这个QObject对象添加了一个过滤器。对于QObject的全部事件来说,都会先经过过滤器的处理,在过滤器里面就可以进行我们自己的处理,比如修改丢弃等,慎用,因为会处理所有的事件,会降低效率(控件级)

  4. 在QApplication中安装事件过滤器:比QObject的过滤器更强大,对所有的QObject的所有事件进行过滤,且第一时间捕获。事件的过滤先经过QApplication的处理再进过QObject的处理,必须慎用(应用级)

  5. 重写QApplication的notify方法,要想在任何事件被处理之前捕获事件,唯一的方法就是重写QApplication的notify方法,一般只在调试中使用(应用级)

    事件处理流程(紫色部分是应用级处理,绿色部分是对象级处理)

例子

import sys

from PyQt5.QtCore import QEvent
from PyQt5.QtWidgets import QApplication, QWidget

class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()

def mousePressEvent(self, mouseEvent):  
    print('MyWidget.mousePressEvent')  
    return QWidget.mousePressEvent(self, mouseEvent)

def event(self, event):  
    if event.type() == QEvent.MouseButtonPress:  
        print('MyWidget.event')  
    return QWidget.event(self, event)

def eventFilter(self, object, event):  
    if event.type() == QEvent.MouseButtonPress:  
        print('MyWidget.eventFilter')  
    return QWidget.eventFilter(self, object, event)

class MyQApplication(QApplication):
def __init__(self, param):
super(MyQApplication, self).__init__(param)

def notify(self, object, event):  
    if event.type() == QEvent.MouseButtonPress:  
        print('MyQApplication.notify')  
    return QApplication.notify(self, object, event)

def eventFilter(self, object, event):  
    if event.type() == QEvent.MouseButtonPress:  
        print('MyQApplication.eventFilter')  
    return QApplication.eventFilter(self, object, event)

if __name__ == '__main__':
app = MyQApplication(sys.argv)
app.installEventFilter(app)
w = MyWidget()
w.installEventFilter(w)
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

信号与槽

信号与槽是PyQt的核心机制,也是对象与对象之间的通信方法。信号与槽函数的对应方式是多对多,且信号可以连接信号。除了控件默认的信号外,可以自己定义和实现信号。

信号定义:

mySignal = pyqtSignal([param])

连接信号到槽:

mySignal.connect(handlerFunc)

发送信号:

mySignal.emit([param])

断开信号与槽:

mySignal.disconnect(handlerFunc)

例子:自定义信号并实现与槽的链接

import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

class MyWidget(QWidget):
mySignal = pyqtSignal()

def \_\_init\_\_(self):  
    super(MyWidget, self).\_\_init\_\_()  
    button = QPushButton(self)  
    button.setText('点我')  
    button.clicked.connect(self.buttonClicked)  
    self.mySignal.connect(self.mySignalHandler)

def buttonClicked(self):  
    print('button clicked emit and handler')  
    self.mySignal.emit()

def mySignalHandler(self):  
    print('my signal emit and handler')

if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

信号与槽高级玩法

信号重载

import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

class MyWidget(QWidget):
# 无参数信号
mySignal_no_aram = pyqtSignal()
# 带一个整型参数信号
mySignal_int = pyqtSignal(int)
# 带一个整型或字符串信号
mySignal_int_or_str = pyqtSignal([int], [str])
# 带两个参数,int和srt 或 str和str
mySignal_two_param = pyqtSignal([int, str], [str, str])

def mySignal\_no\_aram\_handler(self):  
    print('mySignal\_no\_aram\_handler')

def mySignal\_int\_handler(self):  
    print('mySignal\_int\_handler')

def mySignal\_int\_or\_str\_int\_handler(self):  
    print('mySignal\_int\_or\_str\_int\_handler')

def mySignal\_int\_or\_str\_str\_handler(self):  
    print('mySignal\_int\_or\_str\_str\_handler')

def mySignal\_two\_param\_int\_str\_handler(self):  
    print('mySignal\_two\_param\_int\_str\_handler')

def mySignal\_two\_param\_str\_str\_handler(self):  
    print('mySignal\_two\_param\_str\_str\_handler')

def \_\_init\_\_(self):  
    super(MyWidget, self).\_\_init\_\_()  
    button = QPushButton(self)  
    button.setText('点我')  
    button.clicked.connect(self.onClicked)

    # 绑定信号到槽函数  
    self.mySignal\_no\_aram.connect(self.mySignal\_no\_aram\_handler)  
    self.mySignal\_int.connect(self.mySignal\_int\_handler)  
    self.mySignal\_int\_or\_str\[int\].connect(self.mySignal\_int\_or\_str\_int\_handler)  
    self.mySignal\_int\_or\_str\[str\].connect(self.mySignal\_int\_or\_str\_str\_handler)  
    self.mySignal\_two\_param\[int, str\].connect(self.mySignal\_two\_param\_int\_str\_handler)  
    self.mySignal\_two\_param\[str, str\].connect(self.mySignal\_two\_param\_str\_str\_handler)

def onClicked(self):  
    # 发送信号  
    self.mySignal\_no\_aram.emit()  
    self.mySignal\_int.emit(1)  
    self.mySignal\_int\_or\_str\[int\].emit(2)  
    self.mySignal\_int\_or\_str\[str\].emit('abc')  
    self.mySignal\_two\_param\[int, str\].emit(3, 'def')  
    self.mySignal\_two\_param\[str, str\].emit('abc', 'def')

if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

使用自定义参数

import sys
from functools import partial
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
button1 = QPushButton(self)
button1.setText('button1')
button1.move(10, 10)
button2 = QPushButton(self)
button2.setText('button2')
button2.move(10, 50)

    # button1.clicked.connect(lambda: self.onClicked(button1))  
    # button2.clicked.connect(lambda: self.onClicked(button2))  
    # 等价  
    button1.clicked.connect(partial(self.onClicked, button1))  
    button2.clicked.connect(partial(self.onClicked, button2))

def onClicked(self, btn):  
    print("%s" % btn.text())

if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

使用装饰器定义信号与槽

import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
button = QPushButton(self)
button.setText('点击')

    # 设置发送者名称  
    button.setObjectName('button')  
    # 实现绑定  
    QtCore.QMetaObject.connectSlotsByName(self)

# 槽函数命名规则:on\_发送者名称\_发射信号名称(self, param)  
@QtCore.pyqtSlot()  
def on\_button\_clicked(self):  
    print('you clicked button')

if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章