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

在子线程中启动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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:56:50