You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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_())

关键改动说明

  1. CustomDialog优化:添加背景样式,解决无边框窗口的透明问题,同时设置固定大小保证UI展示效果。
  2. Worker类封装:将耗时函数放到子线程执行,通过Qt的信号机制向主线程传递任务状态,避免直接在子线程操作UI(Qt禁止跨线程操作UI元素)。
  3. 装饰器逻辑调整:创建独立线程执行目标函数,主线程专注处理UI事件,确保对话框正常渲染和响应。

内容的提问来源于stack exchange,提问作者Parikshit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 13:05:21