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_())
修改说明
- 修正事件循环启动方式:最后用
sys.exit(main.exec_())正确启动Qt事件循环。 - 移除阻塞主线程的
wait()调用,改用线程的finished信号来串联线程结束逻辑:thd_palier结束后触发thd_offset退出,thd_offset结束后退出应用。 - 将
time.sleep替换为QThread.msleep,更适合Qt线程环境,避免阻塞线程的事件处理(虽然这里影响不大,但属于最佳实践)。 - 移除不必要的
sleep(1)和while not self.thd_palier.isRunning()循环,线程启动是异步的,不需要手动等待。
内容的提问来源于stack exchange,提问作者cyrille_saf
相关产品推荐
相关产品推荐

