欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PyQt5的信号和槽

程序员文章站 2022-07-13 22:31:55
...

普通用法

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

上一篇: 获取窗口句柄

下一篇: etcd集群