專欄地址 ʅ(‾◡◝)ʃ
這一節引入了多線程這個非常重要概念, 在我認為多線程的重要性是緊緊次於信號與槽函數的, 因為在平時經常使用
1. 為什么要用多線程
先看下面這一個示例代碼
6.1
from form import Ui_Form
from PyQt5.QtWidgets import *
import sys
import time
class MyWin(QWidget,Ui_Form):
"""docstring for Mywine"""
def __init__(self):
super(MyWin, self).__init__()
self.setupUi(self)
def test(self): # 這里test就是槽函數, 當點擊按鈕時執行 test 函數中的內容, 注意有一個參數為 self
for i in range(10):
self.pushButton.setText(str(i))
time.sleep(1)
if __name__ == '__main__':
app = QApplication(sys.argv)
mywin = MyWin() # 實例化一個窗口小部件
mywin.setWindowTitle('Hello world!') # 設置窗口標題
mywin.show() #顯示窗口
sys.exit(app.exec())
代碼很簡單, 就是點擊按鈕后, 將按鈕的內容設置為 0, 然后等待一秒后 再設置 為1, 如此循環, 一直設置到 9, 這個過程結束
但是在實際運行的過程中點擊按鈕后就沒有反應了, 一直等待 10 秒后直接將按鈕的內容設置為 9
這是因為圖形化界面必須等待代碼中的 test() 槽函數執行完畢后再更新圖形話界面的內容, 所以直到 test() 函數執行完畢后 按鈕的內容只會被設置為 9, 而沒有中間的設置過程
當然在實際的軟件開發的時候阻塞的時間可能會更長, 想象一下如果你制作一個下載器有一個進度條, 開始時進度還是0 ,過了很長時間突然件進度突然跑滿了, 會讓用戶有一種軟件卡住的錯覺, 這個時候我們就需要使用 PyQt5 的多線程了
2. 怎么使用多線程
有 python 編程基礎的人可能第一個想到的是 threading 這個庫
但這里不是用到 threading , 而是 PyQt5 中的多線程類
示例代碼:
6.2
from form import Ui_Form
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread, pyqtSignal
import sys
import time
class MyWin(QWidget,Ui_Form):
"""docstring for Mywine"""
def __init__(self):
super(MyWin, self).__init__()
self.setupUi(self)
self.mythread = MyThread() # 實例化自己建立的任務線程類
self.mythread.signal.connect(self.callback) #設置任務線程發射信號觸發的函數
def test(self): # 這里test就是槽函數, 當點擊按鈕時執行 test 函數中的內容, 注意有一個參數為 self
self.mythread.start() # 啟動任務線程
def callback(self,i): # 這里的 i 就是任務線程傳回的數據
self.pushButton.setText(i)
class MyThread(QThread): # 建立一個任務線程類
signal = pyqtSignal(str) #設置觸發信號傳遞的參數數據類型,這里是字符串
def __init__(self):
super(MyThread, self).__init__()
def run(self): # 在啟動線程后任務從這個函數里面開始執行
for i in range(10):
self.signal.emit(str(i)) #任務線程發射信號用於與圖形化界面進行交互
time.sleep(1)
if __name__ == '__main__':
app = QApplication(sys.argv)
mywin = MyWin() # 實例化一個窗口小部件
mywin.setWindowTitle('Hello world!') # 設置窗口標題
mywin.show() #顯示窗口
sys.exit(app.exec())
可能看到這部分, 感覺很亂多出了很多代碼, 每行代碼的意義注釋我都已經進行了詳細的標注
這里簡單說一下建立任務線程的步驟:
- 導入需要的 的類
from PyQt5.QtCore import QThread, pyqtSignal其實為了簡單你也可這樣寫from PyQt5.QtCore import *- 編寫任務線程的類 這里的任務線程類是
MyThread並讓它繼承QThread, 並設置觸發信號傳遞的數據類型, 編寫run()函數, 設置觸發- 在
MyWin類中的初始化函數中, 初始化一個任務線程, 設置任務線程觸發后接受的函數- 在合適的位置啟動 任務線程, 比如這里我是在點擊按鈕后啟動的任務線程
- 編寫任務線程觸發的槽函數
callback()
其實剛學到這里的時候, 我也很懵, 但是很多都是固定的寫法, 只要注意上面的幾個關鍵的地方就可以了
啟動程序后, 按鈕的內容從 0 自增加到 9
這里要注意的是 傳遞信號必須事先定義好數據類型, 而傳遞過去的類型必須是已經定義好的數據類型
這里我只說了 任務線程 傳遞給圖形化界面數據(代碼中數據是 0, 1, 2, 3....9), 而沒有圖形界面傳遞給任務線程數據
下一節說明 圖形化界面如何傳遞給任務線程數據
