在事先知道在何时打开对话框时,在PyQt的第二个线程中打开子对话框的正确方法是什么?]

问题描述 投票:0回答:1
我有一个应用程序,在第二个线程中运行某些进程。在此过程中的某些时候,只要满足特定条件,就会打开另一个对话框窗口,该窗口将暂停过程,直到您确认某些内容为止。这将导致以下错误消息:

QObject: Cannot create children for a parent that is in a different thread. (Parent is QApplication(0x1f9c82383d0), parent's thread is QThread(0x1f9c7ade2a0), current thread is QThread(0x1f9c8358800)

有趣的是,如果您还在进程运行时并且在弹出新对话框之前将光标移到MainWindow上,它还会多次产生此错误消息:

QBasicTimer::stop: Failed. Possibly trying to stop from a different thread

非常奇怪。因为如果将光标移到MainWindow上,则会发生

only

现在,在我的应用程序中,我实际上为使用PyQt5.uic.loadUi弹出的新对话框加载了一个界面,这没有引起任何问题。但是,当我为本文创建示例时,由于我在初始化新对话框时设置其布局,因此又发生了另一个问题:

QObject::setParent: Cannot set parent, new parent is in a different thread

导致应用程序崩溃的原因:

Process finished with exit code -1073741819 (0xC0000005)

我显然在这里就我猜想的线程做错了,但是我不知道是什么。我感到特别困惑的是,在使用loadUi完全可以的同时,我无法在初始化期间设置新对话框的布局。这是我的示例代码:

import sys import time import numpy as np from PyQt5.QtCore import QObject, pyqtSignal, QThread from PyQt5.QtWidgets import ( QDialog, QApplication, QPushButton, QGridLayout, QProgressBar, QLabel ) class SpecialDialog(QDialog): def __init__(self): super().__init__() btn = QPushButton('pass variable') btn.clicked.connect(self.accept) layout = QGridLayout() layout.addWidget(btn) # self.setLayout(layout) self.variable = np.random.randint(0, 100) class Handler(QObject): progress = pyqtSignal(int) finished = pyqtSignal(int) def __init__(self): super().__init__() self._isRunning = True self._success = False def run(self): result = None i = 0 while i < 100 and self._isRunning: if i == np.random.randint(0, 100): dialog = SpecialDialog() dialog.exec_() result = dialog.variable time.sleep(0.01) i += 1 self.progress.emit(i) if i == 100: self._success = True self.finished.emit(result) def stop(self): self._isRunning = False class MainWindow(QDialog): def __init__(self): super().__init__() btn = QPushButton('test') btn.clicked.connect(self.run_test) self.pbar = QProgressBar() self.resultLabel = QLabel('Result:') layout = QGridLayout(self) layout.addWidget(btn) layout.addWidget(self.pbar) layout.addWidget(self.resultLabel) self.setLayout(layout) self.handler = None self.handler_thread = QThread() self.result = None def run_test(self): self.handler = Handler() self.handler.moveToThread(self.handler_thread) self.handler.progress.connect(self.progress) self.handler.finished.connect(self.finisher) self.handler_thread.started.connect(self.handler.run) self.handler_thread.start() def progress(self, val): self.pbar.setValue(val) def finisher(self, result): self.result = result self.resultLabel.setText(f'Result: {result}') self.pbar.setValue(0) self.handler.stop() self.handler.progress.disconnect(self.progress) self.handler.finished.disconnect(self.finisher) self.handler_thread.started.disconnect(self.handler.run) self.handler_thread.terminate() self.handler = None if __name__ == '__main__': app = QApplication(sys.argv) GUI = MainWindow() GUI.show() sys.exit(app.exec_())

编辑

[我忘了提到我已经找到this post了,这可能与我的问题有关,但是,我并不理解最佳答案中该解决方案的原因,更重要的是,我不会说我所讲的相信是C ++。

我有一个应用程序,在第二个线程中运行某些进程。在此过程中的某些时候,只要满足特定条件,就会打开另一个对话框窗口,该窗口将暂停过程,直到您...

python pyqt pyqt5 qthread
1个回答
0
投票
如果我们分析平等发生之前的情况,除非最初的进展不同,否则平等发生之后的情况相同,这表明发生平等时必须向GUI发送信号以要求提供信息,以及何时您掌握了这些信息,可以执行相同的任务,但初始进度与发出信号之前的进度相同。
© www.soinside.com 2019 - 2024. All rights reserved.