第六篇 -- 自定义信号与槽使用

举一个例子

human.py

# # 自定义信号与槽的演示
import sys
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal


class Human(QObject):
    # # 定义一个带str类型参数的信号
    nameChanged = pyqtSignal(str)
    # # overload型信号有两种参数,一种是Int,一种是str
    ageChanged = pyqtSignal([int], [str])

    def __init__(self, name="Mike", age=10, parent=None):
        super().__init__(parent)
        self.setAge(age)
        self.setName(name)

    def setAge(self, age):
        self.__age = age
        self.ageChanged.emit(self.__age)  # 发射int参数信号
        if age <= 18:
            age_info = "你是 少年"
        elif 18 < age <= 35:
            age_info = "你是 年轻人"
        elif 35 < age <= 55:
            age_info = "你是 中年人"
        elif 55 < age <= 80:
            age_info = "您是 老人"
        else:
            age_info = "您是 寿星啊"
        self.ageChanged[str].emit(age_info)  # 发射str参数信号

    def setName(self, name):
        self.__name = name
        self.nameChanged.emit(self.__name)


class Responsor(QObject):
    # @pyqtSlot(int)
    def do_ageChanged_int(self, age):
        print("您的年龄是:" + str(age))

    # @pyqtSlot(str)
    def do_ageChanged_str(self, ageInfo):
        print(ageInfo)

    def do_nameChanged(self, name):
        print("Hello, " + name)


if __name__ == "__main__":  # 测试程序
    print("**创建对象时**")
    boy = Human("Boy", 16)
    resp = Responsor()
    boy.nameChanged.connect(resp.do_nameChanged)

    # # overload的信号,两个槽函数不能同名,关联时需要给信号加参数区分
    boy.ageChanged.connect(resp.do_ageChanged_int)
    boy.ageChanged[str].connect(resp.do_ageChanged_str)

    print("\n **建立关联后**")
    boy.setAge(35)
    boy.setName("Jack")

    boy.ageChanged[str].disconnect(resp.do_ageChanged_str)
    print("\n **断开ageChanged[str]的关联后**")
    boy.setAge(10)

 

运行结果为:

1. 信号的定义

定义的类Human是从QObject继承而来的,它定义了两个信号,两个信号都需要定义为类的属性。

nameChanged信号是带有一个str类型参数的信号,定义为nameChanged=pyqtSignal(str)

ageChanged信号是具有两种类型参数的overload型的信号,信号的参数类型可以是int,也可以是str。ageChanged信号定义为:ageChanged=pyqtSignal([int], [str])

 

2. 信号的发射

通过信号的emit()函数发射信号。在类的某个状态发生变化,需要通知外部发生了这种变化时,发射相应的信号。如果信号关联了一个槽函数,就会执行槽函数,如果信号没有关联槽函数,就不会产生任何动作。

 

3. 信号与槽的关联

另外定义的一个类Responsor也是从QObject继承而来的,它定义了三个函数,分别用于与Human类实例对象的信号建立关联。因为信号ageChanged有两种参数类型,要与两种参数的ageChanged信号建立关联,两个槽函数的名称必须不同,所以定义的两个槽函数名称分别是do_ageChanged_int和do_ageChanged_str。需要在创建类的具体实例后在进行信号与槽的关联,所以程序在测试部分先创建两个具体的对象。

boy=Human("Boy", 16)

resp=Responsor()

如果一个信号的名称是唯一的,即不是overload型信号,那么关联时无须列出信号的参数,例如,nameChanged信号的连接为boy.nameChanged.connect(resp.do_nameChanged)

对于overload型的信号,定义信号时的第一个位置的参数是默认参数。例如,ageChanged信号的定义是:ageChanged=pyqtSignal([int], [str]),所以,ageChanged信号的默认参数就是Int型。默认参数的信号关联无须标明参数类型,所以有:

boy.ageChanged.connect(resp.do_ageChanged_int)

但是对于另外一个非默认参数,必须在信号关联时在信号中注明参数,即:

boy.ageChanged[str].connect(resp.do_ageChanged_str)

 

4. 断开信号与槽的关联

在程序中可以使用disconnect()函数断开信号与槽的关联,例如:

boy.ageChanged[str].disconnect(resp.do_ageChanged_str)

 

结论:

  • 创建对象时虽然也发射信号,但还未建立关联,所以无响应
  • 建立关联后,3个信号关联的槽函数都响应了
  • 断开关联后,断开关联的槽函数无响应了

 

ok.

 

posted @ 2020-04-07 14:28  o云淡风轻o  阅读(500)  评论(0编辑  收藏  举报