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

PyQt5中如何从QThread线程返回更新后的dataclass数据类实例

PyQt5 QThread 返回dataclass实现方案

可行性说明

完全可以实现,无法生效的核心原因是自定义信号的参数类型指定错误,以及信号绑定、接收逻辑存在疏漏。

现有代码错误点梳理

  • 自定义finished信号未声明参数类型:当前定义的是无参数信号finished = pyqtSignal(),但run方法里emit时传入了self.data参数,类型不匹配无法传递。之前尝试的pyqtSignal(dataclass)、pyqtSignal(class)写法都是错误的,需要直接传入自定义的dataclass类名info作为参数类型。
  • 信号绑定逻辑错误:绑定了QThread自带的finished信号来触发更新操作,而线程自带的finished信号是无参数的,应该绑定自定义的worker的finished信号来接收传递的dataclass实例。
  • 方法入参不匹配:evt_onFinished方法未定义接收dataclass参数的入参,绑定信号时传入的data变量属于未定义变量。
  • 缺失标签更新逻辑:evt_onFinished方法没有写更新界面标签的具体代码。

修复后的完整代码

import sys
from dataclasses import dataclass

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

@dataclass
class Info():
    fname : str = "8888"
    lname : str = "8888"

class TestThread(QObject):
    # 自定义信号指定参数类型为自定义的Info dataclass
    finished = pyqtSignal(Info)

    def __init__(self, data):
        super().__init__()
        self.data = data
        print(data)

    def run(self):
        print("Update dataclass")
        self.data.fname = "Bob"
        self.data.lname = "Alob"
        # 传递更新后的dataclass实例
        self.finished.emit(self.data)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.data = Info()
        self.setWindowTitle("My App")
        self.resize(200, 200)

        self.lblOne = QLabel("Old Text", self)
        self.lblOne.move(40, 20)
        self.lblOne.resize(100,30)

        self.lblTwo = QLabel("Old Text", self)
        self.lblTwo.move(40, 60)
        self.lblTwo.resize(100,30)

        self.btn = QPushButton("Update Labels", self)
        self.btn.move(40, 100)
        self.btn.clicked.connect(self.runThread)

    def runThread(self):
        self.thread = QThread()
        self.worker = TestThread(self.data)
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        # 绑定自定义finished信号的处理逻辑
        self.worker.finished.connect(self.evt_onFinished)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.start()

    def evt_onFinished(self, updated_data):
        "Update the labels with the information from the returned/updated dataclass"
        self.lblOne.setText(updated_data.fname)
        self.lblTwo.setText(updated_data.lname)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mnuMain = MainWindow()
    mnuMain.show()
    sys.exit(app.exec_())

核心改动说明

  • 修改自定义信号声明为finished = pyqtSignal(Info),明确指定传递参数为自定义的Info dataclass类型
  • 调整信号绑定逻辑,直接将worker的finished信号绑定到evt_onFinished方法,自动传递更新后的dataclass实例
  • 完善evt_onFinished方法的入参和标签更新逻辑
  • 调整了标签的高度避免文字重叠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:15:07