【发布时间】:2014-08-15 13:47:55
【问题描述】:
我在 Python 3.3 中有一个 PyQt5 程序,每次按下按钮时都会启动一个新线程。该线程将使用弹出对话框。它在第一次按下按钮时起作用,但是,第二次(在第一次完成之后)会使程序崩溃。我可以在线程中多次调用对话框,但第二次运行线程时程序会冻结。此代码将重现问题。
import sys
from threading import Thread
from PyQt5 import QtWidgets, QtCore
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(100, 100, 100, 50))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Test"))
self.pushButton.setText(_translate("Dialog", "OK"))
class Ui_MainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
self.pushButton = QtWidgets.QPushButton(mainWindow)
self.pushButton.setGeometry(QtCore.QRect(30, 20, 100, 60))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(mainWindow)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("mainWindow", "Test"))
self.pushButton.setText(_translate("mainWindow", "Push Me!"))
class TestDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# This message simply needs to go away when the button is pushed
self.ui.pushButton.clicked.connect(self.close)
def show_message(self):
super(TestDialog, self).exec_()
class Main(QtWidgets.QMainWindow):
def __init__(self):
super(Main, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.dialog = TestDialog()
self.ui.pushButton.clicked.connect(self.start_thread)
def start_thread(self):
t = Thread(target=self.show_dialog)
t.daemon = True
t.start()
def show_dialog(self):
# Do lots of background stuff here
self.dialog.show_message()
# The dialog can be shown multiple times within the same thread
self.dialog.show_message()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec_())
删除对话框消息,它可以工作。那么为什么我不能从第二个线程调用对话框呢?我不是要同时运行两个线程,而是一个接一个地运行。
【问题讨论】:
-
为什么这么多线程???
-
简而言之:你不应该在非主线程上创建 qwidgets:qt-project.org/doc/qt-5/…
-
@mguijarr:这个想法是在后台对产品进行一些测试。我希望用户能够在测试完成后再次运行测试。
-
@sebastian 我很困惑。我不是在主线程中创建对话框吗?我以为我只是在线程中执行对话框。
-
您从新线程调用
exec- 因此您直接从另一个线程访问小部件,而不是它所在的线程。这是你不应该做的。
标签: python multithreading python-3.x dialog pyqt5