我尝试了一个简单的逻辑来实现这一点:
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_())
这不起作用,因为我收到了对话框,但它是透明的并且不显示消息:
我假设这是因为我的主线程被阻塞,但我不确定情况是否确实如此,以及如果我真的需要走那条路,我如何在装饰器中实现线程。
尝试在不同的线程中运行该函数,当您在主线程中运行该函数时,它有时会阻塞 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
的文档