在子线程中启动QInputDialog并存储输入值时程序崩溃求助
Qt子线程调用QInputDialog导致崩溃的解决方案
问题原因
Qt的UI组件必须在主线程(GUI线程)中创建和操作,子线程中直接调用QInputDialog.getText()会破坏Qt的线程安全机制,导致对话框冻结、程序崩溃。你的代码里get_dialog_value在QRunnable的子线程中执行,直接调用了UI对话框,这是错误的。
修复方案
核心思路:子线程通过信号通知主线程弹出输入对话框,主线程获取用户输入后,再将结果传递给子线程继续后续逻辑。
完整修复代码
from PySide2.QtWidgets import QApplication, QInputDialog, QMainWindow, QPushButton from PySide2.QtCore import * import sys, os class Worker_Class: class WorkerSignals(QObject): finished = Signal() request_input = Signal() # 请求主线程弹出输入框 input_received = Signal(str) # 主线程传递输入结果给子线程 class Worker(QRunnable): def __init__(self): super().__init__() self.signals = Worker_Class.WorkerSignals() self.input_value = "" @Slot() def run(self): # 子线程发送信号,请求主线程弹出输入框 self.signals.request_input.emit() # 等待主线程传递输入结果 loop = QEventLoop() self.signals.input_received.connect(lambda val: self._on_input_received(val, loop)) loop.exec_() # 拿到输入值后执行后续业务逻辑 if self.input_value: print(f"用户输入的内容:{self.input_value}") # 这里可以添加你的其他业务代码 self.signals.finished.emit() def _on_input_received(self, value, loop): self.input_value = value loop.quit() # 退出事件循环,继续子线程逻辑 class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("My App") button = QPushButton("Press Me!") button.clicked.connect(self.start_worker) self.setFixedSize(QSize(400, 300)) self.setCentralWidget(button) self.threadpool = QThreadPool() def start_worker(self): worker = Worker_Class.Worker() # 连接子线程的请求输入信号到主线程的对话框方法 worker.signals.request_input.connect(self.show_input_dialog) self.threadpool.start(worker) @Slot() def show_input_dialog(self): # 主线程中弹出输入对话框 text, ok = QInputDialog.getText(self, "Missing Module Partnumber", "Input Module Partnumber: ") sender = self.sender() if ok and text: sender.input_received.emit(text) else: sender.input_received.emit("") QCoreApplication.setLibraryPaths([os.getcwd() + "\\virtualenv\\Lib\\site-packages\\PyQt5\\Qt5\\plugins"]) app = QApplication(sys.argv) window = MainWindow() window.show() app.exec_()
关键修改点
- 给
WorkerSignals新增request_input和input_received信号,实现子线程与主线程的安全通信。 - 子线程不再直接调用UI对话框,而是通过信号通知主线程处理弹窗逻辑。
- 主线程中单独实现
show_input_dialog方法,确保UI操作在主线程执行,获取输入后再通过信号传回子线程。 - 子线程通过事件循环等待输入结果,拿到值后再继续后续业务逻辑。
额外注意事项
- 所有Qt UI相关操作(创建组件、调用对话框、更新界面)都必须放在主线程中执行。
- 子线程与主线程的通信必须通过信号与槽机制,这是Qt官方推荐的线程安全通信方式。
- 绝对避免在子线程中直接操作任何UI元素,包括对话框、按钮、文本框等。
内容的提问来源于stack exchange,提问作者Aaron Pascua
相关产品推荐
相关产品推荐

