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類型數據