PyQt5中使用線程QThread和Thread進行耗時操作的問題

1、爲什麼使用線程

由於在PyQt5的GUI程序中只存在一個主線程,如果在主線程中進行非常耗時的操作,將會導致GUI界面卡死或者假死,這將十分影響程序的運行,因此在進行耗時的操作,比如有些地方需要使用while 語句,這將會十分耗時,因此使用線程。

2、開啓線程的兩種方式

(1)使用threading包,該方法簡單,只需要兩句就可以開啓一個線程,進行多線程操作,但是該方法有一定的弊端,因爲這是Python中的多線程方法,在QT中會被認爲不是一個安全的線程,因此在該線程中不能更改主程序(進程)中任何控件的狀態。例如設置lineEdit的text值,也是不可以的,當時可以獲取主進程(程序)中控件的值,可以獲取lineEdit的text值。

from threading import Thread
class ServerMain(QMainWindow,Ui_Form):
    def __init__(self):
        super(ServerMain,self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.count_func)#調用函數
        
    def count_func(self):
        t = Thread(target=self.receive)#目標函數
        t.start()#啓動線程

    def receive(self): #線程執行函數
        while True:
            print('-------')

(2)使用QThread類中的run方法,這個啓動線程的方法中,可以更改主控件的值,使用的是迂迴戰術。通過自定義信號,信號發射和接收實現控件值得獲取和更改。使用該方式需要重寫QThread類中的run方法,因此需要多添加一個線程類

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class ClientMain(QMainWindow,Ui_Form):

    def __init__(self):
        super(ClientMain,self).__init__()
        self.setupUi(self)
        #work = WorkThread(content)#類的實例化,也可以在此處實例化,但是如果在此處實例化,
        就不會獲得控件的值,傳遞給線程中的run方法,因此在execute方法中實例化
        self.pushButton.clicked.connect(self.execute)#點擊按鈕,激活方法

    def execute(self):        
        content = self.textEdit.toPlainText()#獲取textEdit中的內容
        work = WorkThread(content)#類的實例化
        work.start()#開啓線程
        work.signals.connect(self.settexts)#信號連接槽函數

    def settexts(self,texts):#帶有一個str參數,用來接收自定義信號傳遞的值
        print(texts+'已經改變')#接收到自定義信號的值
        self.textEdit_2.setText(texts)#設置主控件中textEdit的值

# 繼承QThread,重寫run方法
class WorkThread(QtCore.QThread):    
    signals = pyqtSignal(str)# 定義信號對象,傳遞值爲str類型,使用int,可以爲int類型
    
    def __init__(self,content):#向線程中傳遞參數,以便在run方法中使用
        super(WorkThread, self).__init__()       
        self.content = content
        
    def __del__(self):
        self.wait()
        
    def run(self):#重寫run方法
        while True:
            print(self.content)
            self.signals.emit('接收到服務器數據')#發射信號,str類型數據
            

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章