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
如有錯誤,歡迎指正~