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

如何在函数执行完成前禁用QPushButton按钮?

问题分析与解决方案

问题根源

你的代码里QTimer.singleShot是异步触发的,它不会阻塞当前apply_clicked函数的执行流程。调用QTimer.singleShot后,self.button_apply.setEnabled(True)会立刻执行,导致按钮刚被禁用就瞬间恢复可用,完全达不到“禁用至进程结束”的效果。此外,如果create_credentials_folder是耗时操作,直接在主线程执行还会导致UI卡死,按钮的禁用状态甚至无法正常刷新。

正确实现方案

如果create_credentials_folder是耗时操作,必须用线程来隔离任务与UI主线程,避免UI冻结;任务完成后通过信号槽机制恢复按钮状态。

1. 定义工作线程类

from PyQt5.QtCore import QThread, pyqtSignal

class CredentialsWorker(QThread):
    # 定义任务完成、出错的信号
    task_finished = pyqtSignal()
    task_failed = pyqtSignal(str)

    def __init__(self, samba_path):
        super().__init__()
        self.samba_path = samba_path

    def run(self):
        try:
            # 执行实际的文件夹创建逻辑
            self.create_credentials_folder(self.samba_path)
            self.task_finished.emit()
        except Exception as e:
            self.task_failed.emit(str(e))

    def create_credentials_folder(self, samba_path):
        # 这里替换成你原本的文件夹创建代码,以下是模拟耗时操作示例
        import time
        time.sleep(3)  # 模拟3秒耗时任务
        print(f"Credentials folder created at {samba_path}")

2. 修改按钮点击事件处理

self.button_apply.clicked.connect(self.apply_clicked)

def apply_clicked(self):
    """Events when accept button is pushed""" 
    self.button_apply.setEnabled(False)
    self.text_edit.append("button clicked")   

    # 创建并启动工作线程
    self.worker = CredentialsWorker(self.samba_path_credentials)
    # 连接信号到处理函数
    self.worker.task_finished.connect(self.on_task_done)
    self.worker.task_failed.connect(self.on_task_error)
    self.worker.start()

def on_task_done(self):
    # 任务完成后恢复按钮状态
    self.button_apply.setEnabled(True)
    self.text_edit.append("Credentials folder created successfully")

def on_task_error(self, error_msg):
    # 任务出错也恢复按钮,并提示错误
    self.button_apply.setEnabled(True)
    self.text_edit.append(f"Failed to create folder: {error_msg}")

3. 非耗时场景的简化方案

如果create_credentials_folder操作极快,不需要线程,只需把启用按钮的逻辑放到任务执行后:

def apply_clicked(self):
    """Events when accept button is pushed""" 
    self.button_apply.setEnabled(False)
    self.text_edit.append("button clicked")   

    def execute_task():
        self.create_credentials_folder(self.samba_path_credentials)
        self.button_apply.setEnabled(True)

    QTimer.singleShot(1000, execute_task)

核心要点

  • 耗时任务必须放到子线程执行,避免阻塞UI主线程
  • 按钮状态的恢复必须等待任务实际完成后触发,不能在异步调用后立刻执行
  • 用信号槽机制实现线程与主线程的状态通信,确保UI操作在主线程执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:52:33