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

PySide中QThread显示子窗口时暂停运行与数据传递问题求助

解决方案

要实现线程暂停等待子窗口输入并接收数据的需求,核心是用QWaitCondition + QMutex实现线程的安全暂停/唤醒,配合信号机制让主线程弹出子窗口,输入完成后将数据传递给线程并恢复执行。

关键修改点

  • 给Worker线程添加线程同步工具(QWaitCondition、QMutex),用于暂停线程等待数据。
  • 新增线程槽函数接收主线程传递的输入数据,并唤醒线程。
  • 主线程在收到子窗口数据后,将数据转发给Worker线程。

完整代码

from PySide2 import QtWidgets
from PySide2 import QtCore
import sys, time

class InsertWindow(QtWidgets.QDialog):
    signal_return_data = QtCore.Signal(str)
    def __init__(self):
        super().__init__()

        self.layout = QtWidgets.QVBoxLayout()
        self.line = QtWidgets.QLineEdit("")
        self.push = QtWidgets.QPushButton("Send")
        self.push.clicked.connect(self.send_it)
        self.layout.addWidget(self.line)
        self.layout.addWidget(self.push)
        self.setLayout(self.layout)

    def send_it(self):
        if self.line.text() == '':
            msg = QtWidgets.QMessageBox()
            msg.setText("Cannot be empty!")
            msg.exec_()
        else:
            self.signal_return_data.emit(self.line.text())
            self.close()


class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.layout = QtWidgets.QVBoxLayout()
        self.txt = QtWidgets.QLabel("Welcome!")
        self.push = QtWidgets.QPushButton("Start")
        self.progres = QtWidgets.QProgressBar()
        self.layout.addWidget(self.txt)
        self.layout.addWidget(self.push)
        self.layout.addWidget(self.progres)
        self.setLayout(self.layout)
        self.push.clicked.connect(self.p_start)

    def show_insert_popup(self):
        self.insert_win = InsertWindow()
        self.insert_win.signal_return_data.connect(self.send_to_thread)
        self.insert_win.exec_()

    def p_start(self):
        self.progres.setMinimum(0)
        self.progres.setMaximum(0)
        self.worker = Worker()
        self.worker.signal_open_insert.connect(self.show_insert_popup)
        self.worker.finished.connect(self.stop_)
        self.worker.start()

    def stop_(self):
        self.progres.setMinimum(0)
        self.progres.setMaximum(100)
        self.txt.setText("Thread finished!")

    @QtCore.Slot(str)
    def send_to_thread(self, txt):
        self.txt.setText(f"Received input: {txt}")
        self.worker.set_data(txt)


class Worker(QtCore.QThread):
    signal_open_insert = QtCore.Signal()
    
    def __init__(self):
        super().__init__()
        self.wait_condition = QtCore.QWaitCondition()
        self.mutex = QtCore.QMutex()
        self.received_data = None

    def run(self):
        # 第一阶段工作
        for x in range(2):
            print("I'm working in thread (stage 1)")
            time.sleep(2)
        
        # 请求主线程弹出输入窗口,然后暂停等待数据
        self.signal_open_insert.emit()
        
        # 线程安全的等待:加锁后等待条件触发
        self.mutex.lock()
        self.wait_condition.wait(self.mutex)
        self.mutex.unlock()
        
        # 第二阶段工作,使用收到的数据
        if self.received_data:
            for x in range(2):
                print(f"Here is the data from insert window: {self.received_data}")
                time.sleep(1)

    @QtCore.Slot(str)
    def set_data(self, data):
        # 线程安全的设置数据并唤醒线程
        self.mutex.lock()
        self.received_data = data
        self.wait_condition.wakeOne()
        self.mutex.unlock()


app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
app.exec_()

核心逻辑说明

  1. 线程暂停机制:

    • Worker线程在需要等待输入时,调用wait_condition.wait(self.mutex)进入阻塞状态,释放mutex的同时等待唤醒信号。
    • 主线程传递数据时,先加锁保护共享数据received_data,设置完成后调用wait_condition.wakeOne()唤醒线程,最后解锁。
  2. 数据传递流程:

    • 子窗口输入完成后,通过signal_return_data将数据发送给主线程的send_to_thread槽。
    • 主线程调用Worker的set_data槽,将数据存入线程的received_data并唤醒线程。
    • 线程唤醒后,继续执行后续逻辑,直接使用received_data。
  3. 注意事项:

    • 必须用QMutex配合QWaitCondition,避免线程竞态条件,确保数据设置和线程唤醒的原子性。
    • 子窗口的弹窗要使用exec_()而不是show(),这样会阻塞主线程直到窗口关闭,保证输入完成后再继续后续操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:31:05