У меня есть программа PyQt5 в Python 3.3, которая будет запускать новый поток при каждом нажатии кнопки. Этот поток будет использовать всплывающие диалоговые окна. Он работает при первом нажатии кнопки, однако второй раз (после первого завершения) приведет к сбою программы. Я могу вызвать диалоговое окно столько раз, сколько хочу из потока, но во второй раз, когда поток запускается, программа зависает. Этот код воспроизведет проблему.PyQt5 QDialog в последующих потоках
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_())
Удалить сообщение диалогового окна, и оно работает. Так почему я не могу вызвать диалоговое окно из второго потока? Я не пытаюсь запускать два потока одновременно, но один за другим.
Почему так много нитей ??? – mguijarr
Вкратце: вы не должны создавать qwidgets для non-main-threads: http://qt-project.org/doc/qt-5/thread-basics.html#gui-thread-and-worker-thread – sebastian
@ mguijarr: Идея состоит в том, чтобы запустить некоторые тесты продукта в фоновом режиме. Я хочу, чтобы пользователь смог снова запустить тесты после завершения теста. – Brickmastr