PyQt5的信号和槽

版权声明:所有的博客都是个人笔记,交流可以留言。未经允许,谢绝转载。。。 https://blog.csdn.net/qq_35976351/article/details/88625749

普通用法

给出一个一般的自定义的绑定方式。注意类方法、静态方法和普通方法的区别。如果普通方法作为槽,那么只有绑定了的对应的实例才可以收到信号。其余两个定义后,不需要实例也可以收到。
下面的例子中,receiver1无法接收信号。

from PyQt5.QtCore import pyqtSignal, QObject


class Sender(QObject):
    sendmsg = pyqtSignal(object)  # 这里表明有一个参数

    def __init__(self):
        super(Sender, self).__init__()

    def send_msg(self):
        self.sendmsg.emit("Hello qt5")


class Receiver(QObject):
    def __init__(self):
        super(Receiver, self).__init__()

    def plain_func(self, msg):
        print("plain_func msg: ", msg)

    @classmethod
    def class_func(cls, msg):
        print("class_func msg: ", msg)

    @staticmethod
    def static_func(msg):
        print("static_func msg: ", msg)


receiver = Receiver()
receiver1 = Receiver() 

sender = Sender()
sender.sendmsg.connect(receiver.plain_func)  # 注意这里是实例
sender.sendmsg.connect(Receiver.class_func)
sender.sendmsg.connect(Receiver.static_func)

sender.send_msg()

输出结果:

plain_func msg:  Hello qt5
class_func msg:  Hello qt5
static_func msg:  Hello qt5

进阶用法

信号和槽的参数重载

from PyQt5.QtCore import QObject, pyqtSignal


class Sender(QObject):
    signal_NoParameter = pyqtSignal()
    signal_OneParameter = pyqtSignal(int)
    signal_OneParameterOverload = pyqtSignal([int], [str])
    signal_TwoParameter = pyqtSignal(int, str)
    signal_TwoParameterOverload = pyqtSignal([int, int], [int, str])

    def __init__(self):
        super(Sender, self).__init__()


class Receiver(QObject):
    def __init__(self):
        super(Receiver, self).__init__()

    def setValue_NoParameter(self):
        print("No Parameter")

    def setValue_OneParameter(self, msg):
        print("One Parameter: ", msg)

    def setValue_OneParameterOverload(self, msg):
        print("One Parameter Overload, msg:", msg, "msg type: ", type(msg))

    def setValue_TwoParameter(self, msg1, msg2):
        print("Two Parameter, msg1:", msg1, ", msg2: ", msg2)

    def setValue_TwoParameterOverload(self, msg1, msg2):
        print("Two Parameter Overload, msg1:", msg1, ",msg1 type: ", type(msg1),
              "; msg2:", msg2, ", msg2 type: ", type(msg2))


sender = Sender()
receiver = Receiver()
# 关联信号和槽
sender.signal_NoParameter.connect(receiver.setValue_NoParameter)
sender.signal_OneParameter.connect(receiver.setValue_OneParameter)
sender.signal_OneParameterOverload[int].connect(receiver.setValue_OneParameterOverload)
sender.signal_TwoParameter.connect(receiver.setValue_TwoParameter)
sender.signal_TwoParameterOverload[int, int].connect(receiver.setValue_TwoParameterOverload)
# 发射信号测试
sender.signal_NoParameter.emit()
sender.signal_OneParameter.emit(1)
sender.signal_OneParameterOverload.emit(2)
sender.signal_TwoParameter.emit(2, "World")
sender.signal_TwoParameterOverload.emit(1, 2)

输出结果

No Parameter
One Parameter:  1
One Parameter Overload, msg: 2 msg type:  <class 'int'>
Two Parameter, msg1: 2 , msg2:  World
Two Parameter Overload, msg1: 1 ,msg1 type:  <class 'int'> ; msg2: 2 , msg2 type:  <class 'int'>

使用自定义的参数

假设一个情况,某个按键发出了点击信号,但是该信号不能传递参数,而我们却像知道这是第几次发射该信号的。这可以借助lambda表达式或者偏函数实现。代码如下:

from PyQt5.QtWidgets import QMainWindow, QPushButton, QWidget, \
    QMessageBox, QApplication, QHBoxLayout
from functools import partial
import sys


class WinForm(QMainWindow):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')

        button1.clicked.connect(lambda: self.onButtonClicked(1))  # lambda方式
        button2.clicked.connect(partial(self.onButtonClicked(2))) # 偏函数方式

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)
        self.setCentralWidget(main_frame)

    def onButtonClicked(self, n):
        print('Button {0} is pushed'.format(n))
        QMessageBox.information(self, "Message box",
                                'Button {0} is pushed'.format(n))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec_())

装饰器信号与槽

关于装饰器,可以参考这篇笔记。相当于直接可以定义有函数的信号。一般的使用方式如下:

@QtCore.pyqtSlot(参数)
def on_发送者对象名称_发射信号名称(self, 参数):
	pass

应用代码实例:

# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QWidget, QApplication, \
    QHBoxLayout, QPushButton
from PyQt5 import QtCore
import sys


class CustWidget(QWidget):
    def __init__(self, parent=None):
        super(CustWidget, self).__init__(parent)

        self.okButton = QPushButton("OK", self)
        self.okButton.setObjectName("okButton")  # 发送者的名称
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        self.setLayout(layout)
        QtCore.QMetaObject.connectSlotsByName(self)

    @QtCore.pyqtSlot()
    def on_okButton_clicked(self):
        print("Clicked OK Button")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = CustWidget()
    win.show()
    sys.exit(app.exec_())

每次点击OK按键,控制台都会输出数据。。。

注意一点,QtCore.QMetaObject.connectSlotsByName(self)这句代码是必须的!!!。这段代码的是PyQt5中信号自动连接到槽函数的核心代码。如果使用装饰器的信号和槽,必须有这一句。

断开连接

使用disconnect函数即可

猜你喜欢

转载自blog.csdn.net/qq_35976351/article/details/88625749