淺談PyQt5中非同步重新整理UI和Python多執行緒總結
目前任務需要做一個介面程式,PyQt是非常方便的選擇,QT豐富的控制元件以及python方便的程式設計。近期遇到介面中執行一些後臺任務時介面卡死的情況,解決了在這裡記錄下。
PyQt
PyQt簡介
PyQt是Qt的python介面,PyQt的文件較少,但介面和函式可以完全參照Qt,繼承了Qt中大量的控制元件以及訊號機制,十分方便。以下簡介一個基本的PyQt程式。
- 需要匯入的類主要來自三個包
- from PyQt5.QtWidgets import 常用的控制元件
- PyQt5.QtCore 核心功能類,如QT,QThread,pyqtSignal
- PyQt5.QtGui UI類,如QFont
- 基礎的程式結構:
class Example(QWidget): def __init__(self): super()__init__() self.setupUI() def setupUI(): self.show() pass # 設定UI if __name__ == '__main__': app = QApplication(sys.argv) # 啟動app ex = Example() # 例項化一個自己派生的 # 也可以例項化庫中的控制元件 # q = QPushButton() # q.show() sys.exit(app.exec_())
總體來說:
1. 首先例項化APP
2. 例項化預定義控制元件或者自己派生自庫中的控制元件,記得呼叫show()函式
3. 執行並安全退出
Python中的多執行緒
python中的多執行緒使用較為方便,主要使用threading.Thread類:
1. 執行緒啟動使用start()函式
2. 如果需要等待執行緒執行使用join,這樣主執行緒會阻塞
實現方式一
直接傳入函式,啟動執行緒,可以傳入引數
import time,threading def threadFunction(): while True: print(11111) time.sleep() # 用於命名,可以通過threading.current_thread().name獲得 t = threading.Thread(target=threadFunction,name='funciton') # 如果執行緒有引數 t = threading.Thread(target=threadFunction,args=(),name='funciton') t.start()
實現方式二
繼承Thread,重寫run方法
from threading import Thread import time class Example(Thread): def __init__(self): super().__init__() def run(self): while True: time.sleep(1) print(11111111) if __name__ == '__main__': a = Example() a.start() a.join() print(222222222)
注意:
1. 使用join方法會讓主執行緒阻塞在這裡,等待子執行緒結束,在裡面可以設定阻塞的時間
2. a.setDaemon(True)在start前設定,可以保證在主執行緒終止時,子執行緒也終止
訊號機制
QT中的訊號機制能夠方便的編寫回調。
1. 很多控制元件都有預定的訊號如clicked,直接使用clicked.connect連線槽函式即可。
2. 繼承自Qt的類,然後自定義一個signal類變數,在例項連線訊號就可以了
class Example(QWidget): signal = pyqtSignal() # 括號裡填寫訊號傳遞的引數 # 發射訊號 def func(self): self.signal.emit() # 使用訊號 a = Example() a.signal.connect(callback) # 槽函式 def callback(): pass
UI重新整理
在介面中,通常用會有一些按鈕,點選後觸發事件,比如去下載一個檔案或者做一些操作,這些操作會耗時,如果不能及時結束,主執行緒將會阻塞,這樣介面就會出現未響應的狀態,因此必須使用多執行緒來解決這個問題。
注意:
1. PyQt5不能在子執行緒中重新整理執行緒,這樣會造成介面卡死,因此不能使用常規的多執行緒重新整理UI。
2. 但是又必須要實現子執行緒和主執行緒之間的通訊,否則無法得知任務是否完成。因此使用PyQt5中的QThread,這樣既可以使用訊號機制,又能夠使用多執行緒。
3. 當啟動多執行緒後,註冊訊號,槽函式為主執行緒中的函式,當任務完成後,發射訊號,在主執行緒中對UI進行更新。
注:由於需要註冊訊號,thread需要是繼承自QThread的類
class Example(QThread): signal = pyqtSignal() # 括號裡填寫訊號傳遞的引數 def __init__(self): super().__init__() def __del__(self): self.wait() def run(self): # 進行任務操作 self.signal.emit() # 發射訊號 # UI類中 def buttonClick(self) self.thread = Example() self.thread.signal.connect(self.callback) self.thread.start() # 啟動執行緒 def callbakc(self): pass
如有錯誤,歡迎指正~
以上這篇淺談PyQt5中非同步重新整理UI和Python多執行緒總結就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。