Python?PyQt5?開啟線程防止界面卡死閃退問題解決
Python PyQt5 的界面是主線程執(zhí)行的,如果主線程執(zhí)行了耗時操作,會導(dǎo)致主線程阻塞使得界面卡死閃退。所以,對于一個耗時操作需要開啟一個線程執(zhí)行。
首先導(dǎo)入幾個包:
from PyQt5 import QtCore from PyQt5.QtCore import *
創(chuàng)建一個線程類:
class ListDevicesThread(QtCore.QThread):
signal = pyqtSignal(dict, name='list_devices')
def run(self):
while True:
devices_list = apis.list_devices()
self.signal.emit(devices_list)
time.sleep(5)這個線程每隔 5 秒執(zhí)行一次獲取數(shù)據(jù)的操作。并通過 emit 把數(shù)據(jù)發(fā)送到主界面中。所以,主界面要獲取這個值就需要通過回調(diào)函數(shù)接收:
class Window(QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
# 獲取設(shè)備列表
self.list_shadow_thread = ListDevicesThread()
self.list_shadow_thread.signal.connect(self.after_list_devices)
self.list_shadow_thread.start()- 創(chuàng)建 ListDevicesThread 線程對象,將對象設(shè)置到類成員變量中(如果不設(shè)置,或者設(shè)置重復(fù)的線程變量名,要么讓線程無法執(zhí)行,要么主界面卡死,不能運行程序)。
self.list_shadow_thread.signal.connect(self.after_list_devices)這個代碼的意思是,得到線程對象的信號對象,連接到主界面的after_list_devices函數(shù),這個函數(shù)就是回調(diào)函數(shù),可以接收到emit函數(shù)發(fā)送過來的數(shù)據(jù),數(shù)據(jù)類型在線程中定義(可以是 str、dict 等合法的 py 類型)。- 第三步就是開啟線程并執(zhí)行。
在線程獲取到一次數(shù)據(jù)之后,執(zhí)行下面的回調(diào)函數(shù),回調(diào)函數(shù)收到數(shù)據(jù) data,可以進(jìn)行一些不需要耗時的操作,如果之后還有耗時的操作建議一次性在線程執(zhí)行完成再到這個回調(diào)函數(shù)中來:
def after_list_devices(self, data):
row = 0
self.tableWidget.setRowCount(data['page']['count'])
for item in data['devices']:
self.setTableItem(row, 0, item['device_id'])
self.setTableItem(row, 1, item['device_name'])
self.setTableItem(row, 2, item['product_name'])
self.setTableItem(row, 3, item['status'])
self.setTableItem(row, 4, item['description'])
row += 1到目前為止,上面都是線程執(zhí)行完成之后獲取數(shù)據(jù)發(fā)送給主線程(主界面),是 線程->主線程 的過程。有時候,主線程的一些輸入框里面的值需要發(fā)送給線程,讓線程得到輸入框內(nèi)的值再執(zhí)行下一步操作。這個是 主線程->線程->主線程 的過程。
首先,在線程中創(chuàng)建一個設(shè)置值的函數(shù),如 set_xxx 這樣的格式:
class QueryDeviceThread(QtCore.QThread):
signal = pyqtSignal(dict, name='query_device')
device_id = ''
def set_device_id(self, device_id):
self.device_id = device_id
def run(self):
device = apis.query_device(self.device_id)
self.signal.emit(device)device_id 是線程的類成員變量,通過 set_device_id 函數(shù)給 device_id 設(shè)置新的值。在 run 函數(shù)執(zhí)行的時候,獲取到 device_id 值,這個值要在主界面開啟線程之前設(shè)置好。
點擊界面的按鈕之后觸發(fā)下面的函數(shù),在開啟線程之前,且線程對象創(chuàng)建之后,設(shè)置線程的類成員變量。
def query_device(self):
self.query_device_thread = QueryDeviceThread()
self.query_device_thread.set_device_id(self.input_query_device_id.text())
self.query_device_thread.signal.connect(self.after_query_device)
self.query_device_thread.start()到此這篇關(guān)于Python PyQt5 開啟線程避免界面卡死閃退的文章就介紹到這了,更多相關(guān)Python PyQt5 開啟線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于django2.2連oracle11g解決版本沖突的問題
這篇文章主要介紹了基于django2.2連oracle11g解決版本沖突的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
在PyCharm的 Terminal(終端)切換Python版本的方法
這篇文章主要介紹了在PyCharm的 Terminal(終端)切換Python版本的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08

