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

PyQt中QThread内pyqtSignal定义及信号槽连接异常问题

问题分析与解决

你的代码有两个核心问题导致信号槽无法正常工作:

1. 事件循环未正确启动

最后一行代码main.app.exec_()是错误的,因为main本身就是继承自QCoreApplication的实例,不存在app属性,这会导致Qt的事件循环根本没有启动。而PyQt的信号槽机制依赖事件循环来传递消息,所以信号发射后无法被槽函数接收。

2. 主线程被阻塞

在Main类的__init__方法中调用self.thd_offset.wait(),这个方法会阻塞主线程直到thd_offset线程结束。主线程被阻塞时,事件循环无法运行,信号槽的消息无法被处理,自然无法触发get_data槽函数。

另外,PyCharm提示找不到connect和emit引用是IDE静态检查的问题,运行时不会影响,你可以忽略这个提示,或者更新PyCharm的Qt相关插件来解决。


修正后的代码

import sys
from PyQt5.QtCore import QCoreApplication, QThread, pyqtSignal, pyqtSlot


class Main(QCoreApplication):
    """Main app to start calculation process"""

    def __init__(self, args):
        super(self.__class__, self).__init__(args)

        # thread palier
        self.thd_offset = RunOffsetCalc()
        self.thd_palier = RunStageCalculation()
        self.thd_palier.corr_ray_data.connect(self.thd_offset.get_data)

        # 连接线程结束信号,用于退出应用
        self.thd_offset.finished.connect(self.quit)
        self.thd_palier.finished.connect(self.thd_offset.quit)

        # 启动线程
        self.thd_offset.start()
        self.thd_palier.start()


class RunStageCalculation(QThread):
    """Thread to run calculation for one stage to get averaged corrected radiation values
    for the stage"""

    # [av_ray_vect_corr]
    corr_ray_data = pyqtSignal(str)

    def __init__(self):
        super(self.__class__, self).__init__()

    def run(self):
        print("Execution des calculs pour le palier")
        self.corr_ray_data.emit('test')
        print("Fin d execution des calculs du palier")


class RunOffsetCalc(QThread):
    """Thread to calculate offset giving the corresponding stages and radiation kind"""

    def __init__(self):
        super(self.__class__, self).__init__()
        self.result = None

    @pyqtSlot(str)
    def get_data(self, strg):
        self.result = strg
        print(f"getdata declenchee: {self.result}")

    def run(self):
        print("Lancement RunOffsetCalc")
        while not self.result:
            # 使用QThread的msleep代替time.sleep,更符合Qt线程机制
            QThread.msleep(1000)
        print("Fin d execution RunOffsetCalc")


if __name__ == "__main__":
    main = Main(sys.argv)
    # 正确启动事件循环
    sys.exit(main.exec_())

修改说明

  1. 修正事件循环启动方式:最后用sys.exit(main.exec_())正确启动Qt事件循环。
  2. 移除阻塞主线程的wait()调用,改用线程的finished信号来串联线程结束逻辑:thd_palier结束后触发thd_offset退出,thd_offset结束后退出应用。
  3. 将time.sleep替换为QThread.msleep,更适合Qt线程环境,避免阻塞线程的事件处理(虽然这里影响不大,但属于最佳实践)。
  4. 移除不必要的sleep(1)和while not self.thd_palier.isRunning()循环,线程启动是异步的,不需要手动等待。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:27:30