loading

Python PyQt5 开启线程避免界面卡死闪退

创建线程

file:[src/main.py]
from PyQt5 import QtCore
from PyQt5.QtCore import *

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 秒执行一次获取数据的操作,并通过 emit 把数据发送出去。

使用线程

file:[src/main.py]
class Window(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        # 获取设备列表
        self.list_shadow_thread = ListDevicesThread()
        self.list_shadow_thread.signal.connect(self.after_list_devices)
        self.list_shadow_thread.start()

创建 ListDevicesThread 线程,将线程对象挂载到 self 中,如果不设置,或者设置重复的线程变量名,要么让线程无法执行,要么主界面卡死,不能运行程序。

线程回调函数

在线程获取到一次数据之后,回调函数收到数据 data

file:[src/main.py]
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

完整代码

file:[src/main.py]
from PyQt5 import QtCore
from PyQt5.QtCore import *


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)


class Window(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        # 获取设备列表
        self.list_shadow_thread = ListDevicesThread()
        self.list_shadow_thread.signal.connect(self.after_list_devices)
        self.list_shadow_thread.start()


    # 线程执行完成之后的回调函数
    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

线程获取主线程传递的值

在线程中创建一个设置值的函数,如 set_xxx

file:[src/main.py]
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)

通过 set_device_id 函数给 device_id 设置新的值。在 run 函数执行的时候,获取到 device_id 值。

点击界面的按钮之后触发下面的函数,在开启线程之前,且线程对象创建之后,设置线程的类成员变量。

file:[src/main.py]
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()

完整代码

file:[src/main.py]
from PyQt5 import QtCore
from PyQt5.QtCore import *


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)


class Window(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        # 绑定界面的点击按钮
        self.query_device_button.clicked.connect(self.query_device)


    # 按钮点击的函数
    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()


    # 线程执行完成之后的回调函数
    def after_query_device(self, data):
        print(data)
posted @ 2023-06-21 14:26  Himmelbleu  阅读(191)  评论(0编辑  收藏  举报