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

PyQt5如何点击一个按钮终止另一个按钮触发的运行事件

解决方案

你的代码无法实现中止功能的核心原因是:counter函数直接运行在Qt主线程(UI线程)中,time.sleep(0.1)会完全阻塞主线程的事件循环,导致Abort按钮的点击事件根本无法被响应,自然不可能触发中止逻辑。

你需要将耗时的计数逻辑放到独立的子线程中运行,通过Qt原生的线程中断机制实现安全终止,修改方案如下:


完整修改后代码

from PyQt5 import QtCore, QtGui, QtWidgets
import time

# 新增工作线程类,处理计数逻辑
class CountWorker(QtCore.QThread):
    def run(self):
        for i in range(1000):
            # 判断是否收到中断请求,收到就退出循环
            if self.isInterruptionRequested():
                print("计数已中止")
                break
            print(i)
            # 用QThread自带的毫秒休眠代替time.sleep,避免阻塞事件
            self.msleep(100)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.button = QtWidgets.QPushButton(self.centralwidget)
        self.button.setGeometry(QtCore.QRect(200, 210, 91, 81))
        self.button.setObjectName("button")
        self.sweepbutton = QtWidgets.QPushButton(self.centralwidget)
        self.sweepbutton.setGeometry(QtCore.QRect(460, 210, 93, 81))
        self.sweepbutton.setObjectName("sweepbutton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # 初始化工作线程
        self.count_thread = CountWorker()
        # 绑定Abort按钮的点击事件到中止函数
        self.button.clicked.connect(self.interupt_counter)
        self.sweepbutton.clicked.connect(self.counter)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.button.setText(_translate("MainWindow", "Abort"))
        self.sweepbutton.setText(_translate("MainWindow", "Counter"))

    def counter(self):
        # 避免重复启动线程
        if not self.count_thread.isRunning():
            self.count_thread.start()

    def interupt_counter(self):
        # 线程运行中才触发中止
        if self.count_thread.isRunning():
            # 发送中断请求
            self.count_thread.requestInterruption()
            # 等待线程安全退出
            self.count_thread.wait()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

核心修改说明

  • 新增了CountWorker子线程类继承QThread,将计数逻辑放到run方法中执行,不会阻塞主线程的UI响应
  • 用isInterruptionRequested()判断是否收到中止信号,收到就主动退出循环,是线程安全的终止方式,不会出现资源泄漏
  • 用QThread.msleep()代替time.sleep(),更适配Qt的线程机制
  • Abort按钮点击时调用requestInterruption()发送中止信号,等待线程安全退出
  • 增加了线程运行状态判断,避免重复启动线程或者对未运行的线程执行中止操作

注意:如果后续需要在计数过程中更新UI控件内容,不要直接在子线程的run方法里操作UI,要通过自定义信号槽的方式将数据传递到主线程再更新。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:36:01