PyQt5子线程中如何获取MessageBox的用户点击按钮结果?
解决PyQt5子线程触发弹窗后获取用户点击值的问题
问题根源
- 子线程
function_one发射弹窗信号后立刻读取btn_pressed,但弹窗在主线程显示,用户操作需要时间,此时btn_pressed还未被赋值 show_message方法错误调用了主窗口实例的exec_(),应该调用弹窗自身的exec_()- 自定义
MainMessage类未调用add_btn()方法,导致传入的按钮没有被添加到弹窗中
修改方案
通过新增信号传递弹窗结果,结合QEventLoop让子线程等待用户操作完成,具体步骤:
- 新增
resultSignal信号,用于主线程将弹窗点击结果传回子线程 - 在
function_one中创建事件循环,等待结果信号触发后再执行后续逻辑 - 修正弹窗的按钮添加和执行逻辑
修改后的完整代码
模块代码(main_message.py)
from PyQt5.QtWidgets import QMessageBox class MainMessage(QMessageBox): def __init__(self, title, text, buttons): super(MainMessage, self).__init__() self.setWindowTitle(title) self.setText(text) self.button_list = buttons self.add_btn() # 初始化时直接添加按钮 def add_btn(self): for button_add in self.button_list: self.addButton(button_add) def info(self): self.setIcon(QMessageBox.Information)
主模块代码
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox from PyQt5 import QtCore from main_message import MainMessage import time class MyThread(QtCore.QThread): def __init__(self, func): super(MyThread, self).__init__() self.function_list = func def run(self): for function_to_exec in self.function_list: function_to_exec() class Main(QMainWindow): messageSignal = QtCore.pyqtSignal(str, str, list) resultSignal = QtCore.pyqtSignal(int) # 新增传递结果的信号 def __init__(self): super(Main, self).__init__() self.resize(800, 600) self.function_list = [self.function_one, self.function_two] self.message = MainMessage self.messageSignal.connect(self.show_message) self.btn_pressed = None self.start() def start(self): self.main_thread = MyThread(self.function_list) self.main_thread.start() def function_one(self): time.sleep(3) # 创建事件循环,等待弹窗结果 loop = QtCore.QEventLoop() self.resultSignal.connect(loop.quit) self.messageSignal.emit("提示", "确认操作吗?", [QMessageBox.Ok, QMessageBox.Cancel]) loop.exec_() # 暂停子线程,直到结果信号触发 # 现在可以获取到用户点击结果 print(f"用户点击按钮值:{self.btn_pressed}") if self.btn_pressed == QMessageBox.Ok: print("用户选择了确认") elif self.btn_pressed == QMessageBox.Cancel: print("用户选择了取消") print("fun_one finish") def function_two(self): time.sleep(3) print("fun_two finish") @QtCore.pyqtSlot(str, str, list) def show_message(self, title, text, buttons): new_message = self.message(title, text, buttons) new_message.info() self.btn_pressed = new_message.exec_() # 调用弹窗自身的exec_() self.resultSignal.emit(self.btn_pressed) # 将结果发回子线程 app = QApplication([]) m = Main() m.show() app.exec_()
内容的提问来源于stack exchange,提问作者Revsky01
相关产品推荐
相关产品推荐

