如何在 PyQt 中制作在运行函数之前显示消息并在运行之后隐藏的装饰器?

问题描述 投票:0回答:1

我尝试了一个简单的逻辑来实现这一点:

import sys as _sys
from PySide2 import QtWidgets as _QtWidgets
from PySide2 import QtCore as _QtCore


class CustomDialog(_QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(self.windowFlags() | _QtCore.Qt.FramelessWindowHint)
        layout = _QtWidgets.QVBoxLayout()
        self.label = _QtWidgets.QLabel()
        layout.addWidget(self.label)
        self.setLayout(layout)


def show_message_decorator(func):
    def wrapper(*args, **kwargs):
        dialog = CustomDialog()
        dialog.label.setText("Executing function...")
        dialog.show()
        _QtWidgets.QApplication.processEvents()

        result = func(*args, **kwargs)

        dialog.label.setText("Function completed.")
        _QtWidgets.QApplication.processEvents()
        dialog.hide()

        return result

    return wrapper


@show_message_decorator
def test_function():
    for i in range(500000):
        print(i)


if __name__ == "__main__":
    app = _QtWidgets.QApplication(_sys.argv)
    test_function()
    _sys.exit(app.exec_())

这不起作用,因为我收到了对话框,但它是透明的并且不显示消息:

我假设这是因为我的主线程被阻塞,但我不确定情况是否确实如此,以及如果我真的需要走那条路,我如何在装饰器中实现线程。

python qt user-interface pyqt pyside2
1个回答
0
投票

尝试在不同的线程中运行该函数,当您在主线程中运行该函数时,它有时会阻塞 GUI,使其无响应。

def run_function():
        result = func(*args, **kwargs)
        _QtWidgets.QMetaObject.invokeMethod(
            dialog, "hide", _QtCore.Qt.QueuedConnection
        )
        _QtWidgets.QMetaObject.invokeMethod(
            dialog.label, "setText", _QtCore.Qt.QueuedConnection, 
            _QtCore.Q_ARG(str, "Function completed.")
        )
        return result

    # Run the function in a separate thread
    thread = _QtCore.QThread()
    thread.run = run_function
    thread.finished.connect(dialog.deleteLater)
    thread.start()

我使用 QMetaObject.invokeMethod 来确保线程安全操作,并删除了对话框以防止内存泄漏,这里是关于 QMetaObject.invokeMethod

的文档
© www.soinside.com 2019 - 2024. All rights reserved.