网上一搜,基本都是多线程处理,然后,你从网上搜,看到最多的就是创建一个类,继承QThread类,然后引入一个槽函数,然后改写run方法,将会发生阻塞的代码放在run函数里面,然后通过激活槽函数,传递一个参数,从而实现异步功能:
class MyThread(QThread):
countChanged = pyqtSignal(int)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
self.count = 0
def resetCount(self):
self.count = 0
def run(self):
while True:
self.msleep(100)
self.count += 1
self.countChanged.emit(self.count)
但是对于小白来说,尤其是通过qtdesigner 实现信号与槽的同学来说,好像还是不知道怎么去实现。因此,我讲解一下,我是如何一步一步实现的!
1、在实现之前,首先要搞清楚,这个新创建的可实现异步处理的类,如何在主函数中调用,因此这里就需要知道pyqt5 的自定义信号:
首先先看一下,Pyqt5 自带的clicked 的实现机制
self.Button.clicked.connect(self.Start)
而手动实现,
1)首先声明一个信号,
# 使用自定义信号和UI主线程通讯,参数是发送信号时附带参数的数据类型,可以是str、int、list等
finishSignal = pyqtSignal(list)
2)第二步要明确信号控制的操作,也就是槽函数。信号发出之后我们希望进行的操作,通过信号所在类实例.信号名.connect(槽函数)实现。
# 2.与主线程通信
self.thread_lstm.finishSignal.connect(self.SearchLstm)
def SearchLstm(self,list):
try:
r2, self.best_params = list[0],list[1]
print('r2:', r2)
print('self.best_params:', self.best_params)
self.textEdit_5.append('调试r2:' + str(r2))
self.textEdit_5.append('调试best_params:' + str(self.best_params))
self.Show_Control_OK()
except:
self.Show_Control_Error()
3)最后一步,明确信号的触发机制,我们确定了信号以及信号控制的槽函数,那么什么时候发出这个消息呢,这就需要信号的触发机制,通过信号名.emit(信号内容)实现。
#通过emit函数将参数[]传递给主线程,触发自定义信号
self.finishSignal.emit([self.best_params,self.train_best_score_,self.test_score]) # 注意这里与_signal = pyqtSignal(list)中的类型相同
2.讲解完手动实现信号与槽,基本也就可以理解这个过程,其逻辑就是
1)将耗时的函数添加到一个类中(继承QThread);
在这个类中,在init()中定义耗时函数的入参;定义信号(finishSignal = pyqtSignal(list)),以及发射(self.finishSignal.emit());
2)在主函数中,实例化类,并与主函数通讯;
注:这里有一个点,需要注意:如果信号发射的,就有整数、字符串、列表等,可以将其放到一个容器中(list/dict),统一进行发射输出,等SearchLstm() 接收之后,内部进行拆解;