如何在 Python 函数中创建简单的 PyQt 弹出窗口并在结束时关闭?

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

我是 运行 一个函数,我想在其中打开一个 PyQt 弹出窗口,上面写着类似 "Waiting..." 的内容,它会持续到函数完成所需的时间。之后我想将文本更改为 "Complete",休眠一两秒钟,然后关闭弹出窗口。我已经尝试了很多方法来做到这一点,但到目前为止都没有成功。看起来任何时候我调用 app.exec_() 函数都会停止函数,直到我关闭弹出窗口。我想在 PyQt 的主事件循环的上下文之外执行此操作(我异步尝试 运行 此事件循环无济于事)。如果我不调用 exec_(),我根本看不到弹出窗口。基本上我想要这样的东西:

# 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) 

非常感谢任何帮助。谢谢!

我认为你要执行的任务很重,所以你可以阻止 GUI 循环,所以建议实现一个 QRunnable 并用 QThreadPool 启动它,在 运行方法会调用heavy函数,最后这个task会通过QMetaObject::invokeMethod更新数据,然后我们用一个QEventLoop等待2秒后调用方法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_()

加上:

如果你想调用另一个函数只需更改:

runnable = Runnable(w, func)

至:

runnable = Runnable(w, name_of_your_function)