• 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_())
  • 相关阅读:
    系统架构得11个原则
    深圳变更企业法人
    Mixpanel可以做些什么?
    jira tikcet 过滤版本
    Math.random().toString(36)使用 随机生成数字与字母的组合
    javascript多个等号含义
    登陆dev,AWS需要sso,ip到白名单
    MobSDK已停止支持非严格模式版本,请按上面编译告示接入合规版本!
    thinkphp 变量修饰符
    wsl 关闭 命令
  • 原文地址:https://www.cnblogs.com/chusiyong/p/12929114.html
Copyright © 2020-2023  润新知