第六篇 -- 自定义信号与槽使用
举一个例子
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.