zoukankan      html  css  js  c++  java
  • 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_())
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/chusiyong/p/12929114.html
Copyright © 2011-2022 走看看