简体   繁体   中英

pyqt how to create a wait popup for running a long function/calulation

I am trying to create a dialog window that pops up, runs a function and then automatically closes when the function is done. In the code below, the function runs before popping up the dialog and I cannot automatically close otherwise the dialog window will pop up and not respond to clicking the "x" button.

How can I create a pop-up, run a function after the pop-up is visible, and then close the pop-up when the function is done running.

# from PyQt4 import QtGui
# QtWidgets = QtGui
from PyQt5 import QtWidgets, QtCore
import sys, time

app = QtWidgets.QApplication(sys.argv)


def print_every_3_seconds():
    print(0)
    for i in range(1, 4):
        time.sleep(1)
        print(i)


class RunFunctionDialog(QtWidgets.QDialog):

    def __init__(self, function, parent=None):
        super(RunFunctionDialog, self).__init__(parent)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.textBrowser = QtWidgets.QTextBrowser()
        self.textBrowser.setText("Wait 3 seconds")
        self.layout.addWidget(self.textBrowser)
        self.function = function

    def showEvent(self, QShowEvent):
        self.function()
        # self.close()  # dialog freezes in an unresponsive state


def show_dialog():
    dialog = RunFunctionDialog(print_every_3_seconds)
    dialog.exec_()

widget = QtWidgets.QWidget(None)
button = QtWidgets.QPushButton("Show Dialog", widget)
button.clicked.connect(show_dialog)

widget.show()

app.exec_()

Create a worker thread and put your worker function in there. This will prevent your main (gui) thread from getting blocked by the worker function. You can use the QThread class for this. This has the advantage of having a finished signal that you can use to close your dialog if work is finished.

First you need to create a WorkerThread by simply subclassing QThread:

class WorkerThread(QtCore.QThread):

    def run(self):
        print_every_3_seconds()

Then you create an instance of the Worker class in your RunFunctionDialog.__init__() , connect the finished signal to your close slot and start the thread.

class RunFunctionDialog(QtWidgets.QDialog):

    def __init__(self, function, parent=None):
        super(RunFunctionDialog, self).__init__(parent)
        # ...

        self.function = function

        self.thread = WorkerThread()
        self.thread.finished.connect(self.close)
        self.thread.start()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM