简体   繁体   中英

How to create simple PyQt popup in Python function and close at the end of it?

I'm running a function in which I would like to open a PyQt popup that says something like "Waiting..." which lasts as long as it takes for the function to finish. Afterwards I would like to change the text to "Complete", sleep for a second or two, and close the popup. I've tried several many ways to do this but have been so far unsuccessful. It looks like any time I call app.exec_() the function halts the function until I close the popup. I want to do this outside of the context of the main event loop of PyQt (I tried running this event loop asynchronously to no avail). If I don't call exec_() I never see the popup at all. Basically I want something like this:

# this is the function that is being run
def run():
    create_popup() # show popup
    wait_for_some_messages() # do some stuff
    close_popup() # close popup

def create_popup():
    app = QApplication([])
    popup = Popup()
    popup.show()

class Popup(QDialog):
    super().__init__()
    self.label = QLabel(self) 

Any help is much appreciated. Thanks!

I think the task you want to execute is heavy so you can block the GUI loop so it is recommended to implement a QRunnable and launch it with QThreadPool , in the run method the heavy function will be called, in the end this task will update the data through QMetaObject::invokeMethod , then we will use a QEventLoop to wait 2 seconds and call the method close.

class Runnable(QRunnable):
    def __init__(self, popup, func):
        QRunnable.__init__(self)
        self.popUp = popup
        self.func = func

    def run(self):
        # execute hard function
        self.func()
        # Update the text shown in the popup
        QMetaObject.invokeMethod(self.popUp, "setText",
                                 Qt.QueuedConnection,
                                 Q_ARG(str, "Complete"))
        # wait 2 seconds
        loop = QEventLoop()
        QTimer.singleShot(2000, loop.quit)
        loop.exec_()
        # call the close method of the popup
        QMetaObject.invokeMethod(self.popUp, "close",
                                 Qt.QueuedConnection)


class PopUp(QDialog):
    def __init__(self, *args, **kwargs):
        QDialog.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        self.label = QLabel(self)
        self.layout().addWidget(self.label)

    @pyqtSlot(str)
    def setText(self, text):
        self.label.setText(text)

# emulate the heavy task
def func():
    for i in range(10000):
        print(i)
        QThread.msleep(1)

if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    w = PopUp()
    w.show()
    w.setText("Waiting...")
    runnable = Runnable(w, func)
    QThreadPool.globalInstance().start(runnable)
    w.exec_()

plus:

If you want to call another function just change:

runnable = Runnable(w, func)

to:

runnable = Runnable(w, name_of_your_function)

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