gpt4 book ai didi

python - 使用 QMessageBox 时无法使用 QThread 设置父级错误

转载 作者:太空宇宙 更新时间:2023-11-03 23:56:37 24 4
gpt4 key购买 nike

我试图在一个线程上运行一个进度条,在另一个线程上运行一个函数。以下是我的方法,在我添加 QMessageBox 之前它运行良好。我为 QThread 创建了两个新类,一个处理进度条,另一个我的函数。当使用 onButtonClicked 函数按下按钮时调用它们

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QLineEdit, QProgressBar, QLabel, QFileDialog, QCheckBox, QMenuBar, QStatusBar

import time

TIME_LIMIT = 100
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.msg = QMessageBox()
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(300, 60, 47, 13))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(270, 100, 113, 20))
self.lineEdit.setObjectName("lineEdit")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(290, 150, 75, 23))
self.pushButton.setObjectName("pushButton")
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(280, 210, 118, 23))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.Actionlistenr()

self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))

def Actionlistenr(self):
self.pushButton.clicked.connect(self.onButtonClick)


def test(self):
if self.lineEdit.text() == "":
self.msg.setIcon(QMessageBox.Critical)
self.msg.setText("Please select a document first!")
self.msg.setWindowTitle("Error")
return self.msg.exec()
# If this was just a regular print statement,
# then it would work, or any other statement that
# does not involve a QMessageBox

def onButtonClick(self):
self.calc = External()
self.calc.countChanged.connect(self.onCountChanged)
self.calc.start()
self.calc2 = External2(self)
self.calc2.start()


def onCountChanged(self, value):
self.progressBar.setValue(value)


class External(QThread):
"""
Runs a counter thread.
"""
countChanged = pyqtSignal(int)

def run(self):
count = 0
while count < TIME_LIMIT:
count +=1
time.sleep(1)
self.countChanged.emit(count)

class External2(QThread, object):
"""
Runs a counter thread.
"""
def __init__(self, outer_instance):
super().__init__()
self.outer_instance = outer_instance


def run(self):
self.outer_instance.test()


if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

我收到 QObject::setParent: Cannot set parent, new parent is in a different thread 执行此操作时出错,仅当我在 test 中添加 QMessageBox 时功能。我假设发生这种情况是因为 QMessagebox 在主线程上运行,而不是我的 External2() 类,我该如何解决这个问题?

最佳答案

您要做的第一件事是验证是否满足要求(在本例中 QLineEdit 不为空)以启动重型任务。在这些情况下,我更喜欢使用工作线程方法。要启动繁重的任务,必须异步调用该方法,例如使用 QTimer.singleShot(),并使用 functools.partial() 传递附加参数,您还必须使用 @pyqtSlot 以确保任务在线程正确。

另一方面,您不应修改 Qt Designer(1) 生成的类,而应创建另一个继承自小部件的类并使用第一个类来填充它。

from PyQt5 import QtCore, QtGui, QtWidgets
from functools import partial
import time

TIME_LIMIT = 100


class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(300, 60, 47, 13))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(270, 100, 113, 20))
self.lineEdit.setObjectName("lineEdit")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(290, 150, 75, 23))
self.pushButton.setObjectName("pushButton")
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(280, 210, 118, 23))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.msg = QtWidgets.QMessageBox()

self.Actionlistenr()

thread = QtCore.QThread(self)
thread.start()
self.m_worker = Worker()
self.m_worker.countChanged.connect(self.progressBar.setValue)
self.m_worker.moveToThread(thread)

def Actionlistenr(self):
self.pushButton.clicked.connect(self.onButtonClick)

def request_information(self):
filename = self.lineEdit.text()
if filename:
wrapper = partial(self.m_worker.task, filename)
QtCore.QTimer.singleShot(0, wrapper)
else:
self.msg.setIcon(QtWidgets.QMessageBox.Critical)
self.msg.setText("Please select a document first!")
self.msg.setWindowTitle("Error")
self.msg.exec_()

@QtCore.pyqtSlot()
def onButtonClick(self):
self.request_information()


class Worker(QtCore.QObject):
countChanged = QtCore.pyqtSignal(int)

@QtCore.pyqtSlot(str)
def task(self, filename):
# execute heavy task here
print("start")
print(filename)
count = 0
while count < TIME_LIMIT:
count += 1
time.sleep(1)
self.countChanged.emit(count)
print("finished")


if __name__ == "__main__":
import sys

app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

(1) http://pyqt.sourceforge.net/Docs/PyQt5/designer.html

关于python - 使用 QMessageBox 时无法使用 QThread 设置父级错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57465540/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com