You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在QWidget类的函数中使用QThread实现表格实时更新?

解决方案

核心原则:Qt 所有 GUI 控件的读写、修改操作必须在主线程执行,绝对不能在子线程中直接操作 QTableWidget 等控件,否则会出现随机崩溃、渲染异常等不可预期的问题。

你的需求可以按照标准的 Worker + moveToThread 方案实现,只需要把「拉取实时数据」和「更新UI」逻辑解耦即可,不需要把主窗口绑定的控件对象传到子线程:

  1. 数据拉取逻辑放到子线程的 Worker 类中执行,拉取到数据后通过自定义信号传递给主线程
  2. 主线程收到信号后,再执行表格更新逻辑

以下是修改后的完整可运行代码:

import utility
from PyQt5.QtWidgets import *  
from PyQt5.QtCore import Qt, QThread, QObject, pyqtSignal
import sys

class Worker(QObject):
    # 定义信号,用于将拉取到的行情数据传递到主线程
    data_ready = pyqtSignal(dict)
    finished = pyqtSignal()

    def __init__(self):
        super().__init__()
        # 线程运行标志位,用于控制循环启停
        self.is_running = True

    def run(self):
        while self.is_running:
            # 子线程只负责拉取数据,不碰任何UI控件
            market = utility.get_live_data()
            # 发送数据到主线程
            self.data_ready.emit(market)
            # 可根据需求调整拉取间隔,示例为间隔1秒拉取一次
            QThread.msleep(1000)
        self.finished.emit()

class mainUI(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent, Qt.WindowStaysOnTopHint)
        self.setMinimumSize(1000, 500)

        self.table_live = QTableWidget()
        self.table_live.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_live.setColumnCount(6)
        self.table_live.setHorizontalHeaderLabels(
        ['Name', 'Quantity', 'Discount Price', 'Market Price', 'Change', 'P/L']
        )

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.table_live)
        self.setLayout(self.layout)

        # 初始化Worker和线程
        self.worker = Worker()
        self.update_thread = QThread()
        # 将worker迁移到子线程
        self.worker.moveToThread(self.update_thread)

        # 绑定信号槽
        self.update_thread.started.connect(self.worker.run)
        self.worker.data_ready.connect(self.update_table_live)
        # 线程退出相关信号绑定,避免内存泄漏
        self.worker.finished.connect(self.update_thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.update_thread.finished.connect(self.update_thread.deleteLater)

        # 启动线程
        self.update_thread.start()

    def update_table_live(self, market):
        """主线程中负责更新表格的槽函数,只处理UI逻辑"""
        self.table_live.setRowCount(0)
        for name, product_data in market.items():
            row_count = self.table_live.rowCount()
            self.table_live.insertRow(row_count)

            item_name = QTableWidgetItem(name)
            item_quantity = QTableWidgetItem(product_data['quantity'])
            item_discount = QTableWidgetItem(product_data['discount'])
            item_current = QTableWidgetItem(product_data['price'])
            item_change = QTableWidgetItem(product_data['change'])
            item_pl = QTableWidgetItem(product_data['p_l'])

            self.table_live.setItem(row_count, 0, item_name)
            self.table_live.setItem(row_count, 1, item_quantity)
            self.table_live.setItem(row_count, 2, item_discount)
            self.table_live.setItem(row_count, 3, item_current)
            self.table_live.setItem(row_count, 4, item_change)
            self.table_live.setItem(row_count, 5, item_pl)

    def closeEvent(self, event):
        """重写窗口关闭事件,保证线程正常退出"""
        self.worker.is_running = False
        self.update_thread.wait()
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = mainUI()
    win.show()
    app.exec_()

内容的提问来源于stack exchange,提问作者mehulJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 11:15:04