В PyQt5 новый родитель находится в другом Qthread после всплывающего QMessageBox - PullRequest
0 голосов
/ 10 ноября 2018

Это код PyQt5. Я хочу отсчитывать 5 секунд и обновлять каждую 1 секунду. Затем приложение вызовет QMessageBox.
Но оно будет закрыто после нажатия кнопки на QMessageBox из-за QObject::setParent: Cannot set parent, new parent is in a different thread,
подробного кода ниже:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys, time
from _thread import *

class ThreadClass(QtCore.QThread):
    # Create the signal
    sig = QtCore.pyqtSignal(int)

    def __init__(self, mw, parent=None):
        self.mw = mw
        self.mbox = QtWidgets.QMessageBox()
        super().__init__(parent)
        self.sig.connect(self.showtime)

    def showtime(self, t):
        self.mw.label.setText(str(t))

    def run(self):
        for t in range(5):
            self.sig.emit(t)
            time.sleep(1)
        self.mbox.about(QtWidgets.QMainWindow(), "Title", "Finished")

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(253, 181)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(90, 100, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(20, 20, 211, 16))
        self.label.setObjectName("label")
        self.tc = ThreadClass(self)
        self.pushButton.clicked.connect(lambda: self.tc.start())
        #self.pushButton.clicked.connect(lambda: start_new_thread(showtime, (self.label, )))
        MainWindow.setCentralWidget(self.centralwidget)


        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.pushButton.setText("Show")
        self.label.setText("Time")         

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Ui_MainWindow()
    w = QtWidgets.QMainWindow()
    ex.setupUi(w)
    w.show()
    sys.exit(app.exec_())

Приложение закроется после нажатия кнопки на QMessageBox и сообщения об ошибке ниже.

QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QObject::setParent: Cannot set parent, new parent is in a different thread
QObject::setParent: Cannot set parent, new parent is in a different thread

1 Ответ

0 голосов
/ 10 ноября 2018

Попробуйте:

import sys   #, time
from PyQt5 import QtCore, QtGui, QtWidgets
from _thread import *

class ThreadClass(QtCore.QThread):
    # Create the signal
    sig = QtCore.pyqtSignal(int)
    finish = QtCore.pyqtSignal()                # +++

    def __init__(self, mw, parent=None):
#        self.mw = mw
#        self.mbox = QtWidgets.QMessageBox()
        super().__init__(parent)
#        self.sig.connect(self.showtime)

#    def showtime(self, t):
#        self.mw.label.setText(str(t))

    def run(self):
        for t in range(5):
            self.sig.emit(t)
            #time.sleep(1)
            QtCore.QThread.msleep(1000)

        self.finish.emit()                                             # +++
#        self.mbox.about(QtWidgets.QMainWindow(), "Title", "Finished")

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(253, 181)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(90, 100, 75, 23))
        self.pushButton.setObjectName("pushButton")

        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(20, 20, 211, 16))
        self.label.setObjectName("label")

        self.tc = ThreadClass(self)
        self.pushButton.clicked.connect(lambda: self.tc.start())
        #self.pushButton.clicked.connect(lambda: start_new_thread(showtime, (self.label, )))

        self.tc.sig.connect(self.showtime)            # +++
        self.tc.finish.connect(self.finishTime)       # +++


        MainWindow.setCentralWidget(self.centralwidget)


        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.pushButton.setText("Show")
        self.label.setText("Time")         

# +++
    def showtime(self, t):
        self.label.setText(str(t)) 

# +++
    def finishTime(self):
        self.mbox = QtWidgets.QMessageBox()
        self.mbox.about(QtWidgets.QMainWindow(), "Title", "Finished")


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w   = QtWidgets.QMainWindow()
    ex  = Ui_MainWindow()
    ex.setupUi(w)
    w.show()
    sys.exit(app.exec_())

enter image description here

...