3.3 信号和槽的创建+自定义信号(pyqtSignal)的原理和方法


一、信号和槽的创建

1.信号和槽的介绍

  • 每一个QObject对象和所有继承自QWidget的控件(这些都是 QObject 的子对象)都支持信号与槽机制。
  • 当信号发射时,连接的槽函数将会自动执行。
  • 信号与槽通过object.signal.connect()方法连接。

信号与槽具有如下特点。

  • 一个信号可以连接多个槽。
  • 一个信号可以连接另一个信号。
  • 信号参数可以是任何Python类型。
  • 一个槽可以监听多个信号。
  • 信号与槽的连接方式可以是同步连接,也可以是异步连接。
  • 信号与槽的连接可能会跨线程。
  • 信号可能会断

示意图:

API中信号与槽的更详细解释,可以参考官方网站:

2.定义信号

1> 为QObject对象创建信号

  • 使用pyqtSignal()函数创建一个或多个重载的未绑定的信号作为类的属性,信号只能在QObject的子类中定义
  • 信号必须在类创建时定义,不能在类创建后作为类的属性动态添加进来。
  • 信号可以传递多个参数,并指定信号传递参数的类型,参数类型是 标准的Python数据类型(字符串、日期、布尔类型、数字、列表、元组和字典)
    2> 为控件创建信号
  • 为自定义控件WinForm创建了一个btnClickedSignal信号。
class WinForm(QMainWindow):
btnClickedSignal=pyqtSignal()

3.操作信号

  • 使用connect()函数可以把信号绑定到槽函数上
  • 使用disconnect()函数可以解除信号与槽函数的绑定
  • 使用emit()函数可以发射信号

4.信号与槽的入门应用

1>内置信号与槽的使用

  • 是指在发射信号时,使用窗口控件的函数,而不是自定义的函数。
  • 代码
from PyQt5.QtWidgets import QPushButton, QApplication, QWidget
from PyQt5.QtWidgets import QMessageBox
import sys

app = QApplication(sys.argv)
widget = QWidget()


def showMsg() :
    QMessageBox.information(widget, "信息提示框", "ok,弹出测试信息")


btn = QPushButton("测试点击按钮", widget)
btn.clicked.connect(showMsg)
widget.show()
sys.exit(app.exec_())

  • 效果

2>自定义信号与槽的使用

  • 指在发射信号时,不使用窗口控件的函数,而是使用自定义的函数(简单地说,就是使用 pyqtSignal 类实例发射信号)
  • 代码
"""
    【简介】
    内置信号槽示例
"""

from PyQt5.QtCore import QObject, pyqtSignal


# 信号对象
class QTypeSignal(QObject) :
    # # 定义一个信号
    # sendmsg = pyqtSignal(object)

    #定义含有两个参数的信号
    sendmsg = pyqtSignal(str,str)

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

    def run(self) :
        # 发射信号
        # # 传递一个参数
        # self.sendmsg.emit('Hello Pyqt5')
        # 传递两个参数
        self.sendmsg.emit('第一个参数', '第二个参数')


# 槽对象
class QTypeSlot(QObject) :
    def __init__(self) :
        super(QTypeSlot, self).__init__()

    # 槽对象里的槽函数

    # def get(self, msg) :
    #     print("QSlot get msg => " + msg)

    def get(self, msg1, msg2) :
        print("QSlot get msg => " + msg1 + ' ' + msg2)


if __name__ == '__main__' :
    send = QTypeSignal()
    slot = QTypeSlot()
    # 1
    print('--- 把信号绑定到槽函数 ---')
    send.sendmsg.connect(slot.get)
    send.run()

    # 2
    print('--- 把信号断开槽函数 ---')
    send.sendmsg.disconnect(slot.get)
    send.run()
  • 运行结果

3>装饰器的信号与槽的使用

  • 是第一种的衍生,后面会介绍

5.自定义信号(pyqtSignal)的原理和方法

1> 基本原理

  • 自定义信号是通过pyqtSignal函数以类属性的方式在被重写的类内部实现的,这里的类属性和实例属性一定要区分清楚,不能再pyqtSignal之前加self。
  • pyqtSignal()函数也可以传递不同的参数。

2> 代码

  • 思路:
    自定义按钮类:
    1.定义好一个信号
    2.寻找这个信号所触发的事件
    3.在事件内部调用父类功能事件+逻辑判断->通过emit函数把定义的信号发出去
    定义窗口类:
    1.init函数
    2.func_list函数
    3.对应func函数->内部定义槽函数+利用自定义信号connect连接
点击查看代码
from PyQt5.Qt import *
import sys

#自定义信号
class Btn(QPushButton) :
    rightSignal = pyqtSignal()  # 先定义好一个信号,然后寻找这个信号所属事件
    #通过事件来触发,需要重写事件
    def mousePressEvent(self, evt) :
        super().mousePressEvent(evt) #调用父类功能
        # print(evt.button())  # QMouseEvent
        # if evt.button() == 2:
        if evt.button() == Qt.RightButton :#左键是1 右键是2
            # print('鼠标右键被按下')  # 这是用来测试右键是否生效,不是槽函数功能
            self.rightSignal.emit()  # 通过emit函数来把之定义的信号发射出去,以实现后面与槽函数的连接
        pass


class Window(QWidget) :
    def __init__(self) :
        super().__init__()
        self.setWindowTitle("自定义信号的原理和方法")
        self.resize(600, 500)
        self.func_list()

    def func_list(self) :
        self.func()

    def func(self) :
        # btn = QPushButton(self)
        btn = Btn(self)
        btn.setText('按钮')
        btn.move(200, 100)

        #槽函数
        def btn_press() :
            print('鼠标被按下')

        #btn.pressed.connect(btn_press)  #内置信号pressed与槽函数连接,只有左键按时会有反应
        btn.rightSignal.connect(btn_press) #用自定义信号连接槽函数,并把槽函数内的内容输出


if __name__ == '__main__' :
    app = QApplication(sys.argv)
    window = Window()

    window.show()
    sys.exit(app.exec_())
  • 运行结果
    右键点击按钮,输出


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM