定义了一个QT线程类,采用信号槽来传递信息,刷新控件,参数func为循环执行的函数名,main为该函数所在的实体类,cla为信号的类型。
这里我希望能自定义信号类型,而以下代码有会报错标题的信息。
class MySerThread(QtCore.QThread): #信号槽定义 # 定义信号,自定义参数为cla类型 breakSignal = QtCore.pyqtSignal(str) def __init__(self,func:str, main, cla, parent=None): super().__init__(parent) # 下面的初始化方法都可以,有的python版本不支持 # super(Mythread, self).__init__() self.cla = cla self.ss = func self.main = main def set_class(self): self.breakSignal = QtCore.pyqtSignal(self.cla) def run(self): while True: self.ret = '' #使用ret无效,必须加self exec("self.ret=self.main.{}()".format(self.ss)) #执行表达式 self.ret=self.main.read_thead() self.breakSignal.emit(self.ret) #信号槽传递 self.quit()
原因分析:参考https://fishc.com.cn/thread-60309-1-1.html一个信号(特别是一个未绑定的信号)是类中的一个属性当信号作为属性被实例化后,PyQt5会自动绑定到实例信号并创建一个绑定的信号。这和Python自身创建绑定方法的功能类似。
根据文档,信号得是类的属性才可以。但放在__init__里并不是一个属性,是个啥,不知道,暂且叫他局部变量吧。
以下尝试均失败:
1、重新声明信号类型的
self.t1.breakSignal = QtCore.pyqtSignal(str)
2、利用 @property 装饰器将函数声明为属性的
@property def breakSignal(self) return QtCore.pyqtSignal(int)
3、利用lambda 关键字
breakSignal = lambda a,b: QtCore.pyqtSignal(b)
4、property
def breakSignal_(self): return QtCore.pyqtSignal(int) breakSignal = property(breakSignal_)
曲线救国:
1、定义多个信号类型,使用if判断类型
breakSignal_int = QtCore.pyqtSignal(int) breakSignal_str = QtCore.pyqtSignal(str) def __init__(self,func:str, main, cla, parent=None): super().__init__(parent) # 下面的初始化方法都可以,有的python版本不支持 # super(Mythread, self).__init__() self.cla = cla self.ss = func self.main = main @property def my_code(self): if self.cla == int: return self.breakSignal_int elif self.cla == str: return self.breakSignal_str def my_emit(self, ret): if self.cla == int: self.breakSignal_int.emit(self.ret) elif self.cla == str: self.breakSignal_str.emit(self.ret) def run(self): while True: self.ret = '' #使用ret无效,必须加self exec("self.ret=self.main.{}()".format(self.ss)) #执行表达式 self.ret=self.main.read_thead() self.my_emit(self.ret) #信号槽传递 self.quit() #线程退出
2、object支持任意类型
QtCore.pyqtSignal('PyQt_PyObject')
分析:
在qt线程实例化时已经完成信号的绑定,对应breakSignal 的地址,当重新赋值时self.breakSignal = QtCore.pyqtSignal(self.cla) 重新赋python将创建一个新的内存地址并赋值,这将导致信号未绑定,找不到connect。
验证:在init中加入:
print(self.breakSignal_str) self.breakSignal_str = QtCore.pyqtSignal(str) print(self.breakSignal_str)
输出结果:
<bound PYQT_SIGNAL breakSignal_str of MySerThread object at 0x000001B4043CA828>
<unbound PYQT_SIGNAL [str]>
未绑定,结果显而易见了
那么有没有办法手动绑定呢?
没办法!!
手册中:
信号(特别是未绑定的信号)是类属性。当信号被引用为该类实例的属性时,PyQt5会自动将该实例绑定到该信号,以创建绑定信号。这与Python本身用于从类函数创建绑定方法的机制相同。
一个绑定信号具有connect(),disconnect()和emit()实现相关联的功能的方法。
https://stackoverflow.com/questions/50294652/how-to-create-pyqtsignals-dynamically
此坑待填!!!!!!!!!
同时记录一下,pyqt中不能使用sleep等延时函数,会造成GUI卡主,切无法定位原因!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
如果必须sleep,建议使用线程加信号槽的形式。