如何在PyQt中实现函数执行前后显示/隐藏提示的装饰器?
问题原因与解决方案
你的推测完全正确——主线程被耗时函数阻塞是核心问题。虽然你调用了processEvents(),但test_function里的循环执行密度极高,UI线程根本没有足够时间完成对话框的渲染;再加上你设置了FramelessWindowHint(无边框窗口),默认无背景层,最终导致对话框呈现透明状态。
下面是修复后的完整实现,同时解决UI阻塞和窗口透明问题:
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) # 给无边框窗口添加背景与边框,解决透明问题 self.setStyleSheet("background-color: white; border: 1px solid #ccc;") layout = _QtWidgets.QVBoxLayout() self.label = _QtWidgets.QLabel() layout.addWidget(self.label, alignment=_QtCore.Qt.AlignCenter) self.setLayout(layout) # 设置固定大小,避免窗口过小 self.setFixedSize(220, 110) class Worker(_QtCore.QObject): # 定义信号:任务完成、结果返回 finished = _QtCore.Signal() result_ready = _QtCore.Signal(object) def __init__(self, func, args, kwargs): super().__init__() self.func = func self.args = args self.kwargs = kwargs def run(self): # 在子线程执行耗时逻辑 task_result = self.func(*self.args, **self.kwargs) self.result_ready.emit(task_result) self.finished.emit() def show_message_decorator(func): def wrapper(*args, **kwargs): dialog = CustomDialog() dialog.label.setText("Executing function...") dialog.show() # 创建子线程与工作对象 worker = Worker(func, args, kwargs) thread = _QtCore.QThread() worker.moveToThread(thread) # 绑定信号槽:线程启动执行任务,任务完成后清理资源、更新UI thread.started.connect(worker.run) worker.finished.connect(thread.quit) worker.finished.connect(worker.deleteLater) thread.finished.connect(thread.deleteLater) # 任务完成时更新对话框文本并隐藏 worker.finished.connect(lambda: dialog.label.setText("Function completed.")) worker.finished.connect(dialog.hide) # 启动线程 thread.start() # 保持UI响应直到对话框关闭 while dialog.isVisible(): _QtWidgets.QApplication.processEvents(_QtCore.QEventLoop.AllEvents, 100) # 返回任务结果 return worker.result_ready return wrapper @show_message_decorator def test_function(): for i in range(500000): print(i) return "Task completed successfully!" if __name__ == "__main__": app = _QtWidgets.QApplication(_sys.argv) task_result = test_function() print(task_result) _sys.exit(app.exec_())
关键改动说明
- CustomDialog优化:添加背景样式,解决无边框窗口的透明问题,同时设置固定大小保证UI展示效果。
- Worker类封装:将耗时函数放到子线程执行,通过Qt的信号机制向主线程传递任务状态,避免直接在子线程操作UI(Qt禁止跨线程操作UI元素)。
- 装饰器逻辑调整:创建独立线程执行目标函数,主线程专注处理UI事件,确保对话框正常渲染和响应。
内容的提问来源于stack exchange,提问作者Parikshit
相关产品推荐
相关产品推荐

