PyQt5事件处理

事件介绍

事件的处理机制非常的复杂,属于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_())
原文地址:https://www.cnblogs.com/chusiyong/p/12929114.html