PyQt5学习笔记:子线程与子线程之间数据传输,利用主线程实现(包括主线程传给子线程参数实现)

今天想要实现子线程与子线程之间参数的传送,而且是要实现动态传参,上网搜了好久,然后又自己尝试,结果发现实在不知道如何直接实现两个子线程之间参数的传递(利用实例化时参数无法实现动态传参),使用信号与槽机制结果传到另一个线程里的不知道是啥。最后采用了子线程->主线程->子线程的思路。

这里需要搞明白信号发送与接受,还有主线程动态传参到子线程。首先看一下界面:

PyQt5学习笔记:子线程与子线程之间数据传输,利用主线程实现(包括主线程传给子线程参数实现)_第1张图片

 我想要实现label标签内的数字随着进度的变化而变化,利用线程实现(当然有更简单的方法,这里仅是为了了解线程)。

建立两个线程类:

from PyQt5 import QtWidgets, QtCore
import sys
from PyQt5.QtCore import *
import time
 
 
# 继承QThread
class Runthread(QtCore.QThread):
    #  通过类成员对象定义信号对象
    _signal = pyqtSignal(str)
    _signal2 = pyqtSignal(str)
 
    def __init__(self):
        super(Runthread, self).__init__()
 
    def __del__(self):   
        self.wait()
 
    def run(self):
        for i in range(100):
            time.sleep(0.05)
            self._signal.emit(str(i))  # 注意这里与_signal = pyqtSignal(str)中的类型相同
            self._signal2.emit(str(i))
        self._signal.emit(str(100))
        self._signal2.emit(str(100))
class SecondThread(QThread):   #创建的第二线程类
    sin = pyqtSignal(str)
    def __init__(self):
        super(SecondThread,self).__init__()
        self.Q = None
        
    def accept(self,num):    #接受Ui线程也就是主线程传参
        self.Q = num
        self.sin.emit(self.Q)
    def run(self):  #注意不要把信号发出写在run里,否侧会导致信号无法发出或者仅仅发出一次空信号
        pass

上面为了便于处理,这里在第一个线程里传出的设置两个信号,一个和进度条连接,不再多问,主要关注如何将第二个信号传给主线程再传给子线程,最后(一般是需要再第二个线程里经过复杂计算)再传回主线程需要的数据,这里第二个线程不做多余计算直接传回。

 

class Example(QtWidgets.QWidget):
    signal = pyqtSignal(str)   #定义一个主线程
    def __init__(self):
        super().__init__()
        
        # 按钮初始化
        self.button = QtWidgets.QPushButton('开始', self)
        self.button.setToolTip('这是一个 QPushButton widget')
        self.button.resize(self.button.sizeHint())
        self.button.move(120, 80)
        self.button.clicked.connect(self.start_login)  # 绑定多线程触发事件
        
        self.label = QtWidgets.QLabel(self)
        self.label.setGeometry(QtCore.QRect(0,0,40,40))
        self.label.setFrameShape(QtWidgets.QFrame.Box)
        # 进度条设置
        self.pbar = QtWidgets.QProgressBar(self)
        self.pbar.setGeometry(50, 50, 210, 25)
        self.pbar.setValue(0)
        self.num = None
        # 窗口初始化
        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('OmegaXYZ.com')
        self.show()
        self.thread = None  # 初始化线程
        self.thread2 = None

    def changednum(self,num):   #将线程一的参数传给变量,在由主线程信号传出
        self.num = num
        self.signal.emit(self.num)
 
    def start_login(self):
        # 创建线程
        self.button.setEnabled(False)
        self.thread = Runthread()
        # 连接信号
        self.thread._signal.connect(self.call_backlog)  # 进程连接回传到GUI的事件
        self.thread._signal2.connect(self.changednum)       
        # 开始线程
        self.thread.start()      
        self.thread2 = SecondThread()
        self.signal.connect(self.thread2.accept)
        self.thread2.sin.connect(self.labelset)
        self.thread2.start() 
    def call_backlog(self, msg):
        self.pbar.setValue(int(msg))  # 将线程的参数传入进度条
        if msg == '100':
            self.thread.terminate()   #结束线程
            self.thread2.terminate()
            self.button.setEnabled(True)  #激活按钮

    def labelset(self,num):
        self.label.setText(num)
 
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    myshow = Example()
    myshow.show()
    sys.exit(app.exec_())

 我们能够看到主线程接受到了第一个子线程thread的信号,也就是进度条的数值,这里我们需要注意在信号与槽的机制里信号可以在线程之间传送!所以信号可以从主线程直接传送到子线程内。

这里主线程传送到子线程我利用了changednum将一个变量作为中间变量(其实也无所谓),重要的是利用主线程的信号将值传给子线程。

你可能感兴趣的:(PyQt5,python,pyqt5)