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

QtCore.QTimer间隔时间随启动次数递增问题求助

PyQt5计时器间隔异常变长问题的原因及解决

问题描述

我用PyQt5开发了带有「Start Timer」和「Stop Timer」按钮的界面,期望每次点击「Start Timer」时,QtCore.QTimer能以1秒间隔持续计时。但实际运行时,第一次启动间隔为1秒,第二次变为2秒,后续每次启动间隔还会持续变长,想知道该错误的原因。

代码实现

from PyQt5 import QtWidgets, QtGui, QtCore

class CustomWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.layout  = QtWidgets.QGridLayout()
        self.button1 = QtWidgets.QPushButton("Start Timer")
        self.button2 = QtWidgets.QPushButton("Stop Timer")
        self.label1  = QtWidgets.QLabel("")
        self.label1.setWordWrap(True)
        self.timer=QtCore.QTimer()
        self.layout.addWidget(self.button1, 0, 0)
        self.layout.addWidget(self.button2, 0, 1)
        self.layout.addWidget(self.label1, 1, 0, 1, 3)
        self.setLayout(self.layout)
        self.layout.setColumnStretch(2, 1)
        self.layout.setRowStretch(2, 1)
        self.button1.clicked.connect(self.start_timer)
        self.button2.clicked.connect(self.stop_timer)

    def start_timer(self):
        self.timer.timeout.connect(self.startPressed)
        self.timer.start(1000)
        self.timer.setInterval(1000)
        self.timecount=0

    def startPressed(self):
        self.label1.setText(str(self.timecount))
        self.timecount=self.timecount+1

    def stop_timer(self):
        self.timer.stop()

class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.cw = CustomWidget()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.cw)

        self.setLayout(self.layout)
        self.show()

QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
app = QtWidgets.QApplication([])
win = App()
status = app.exec_()

错误原因

核心问题是每次点击「Start Timer」时,都会重复给timeout信号绑定同一个槽函数startPressed:

  • 第一次点击启动,timeout信号绑定1次startPressed,计时器每秒触发1次,槽函数执行1次,timecount每秒+1,间隔正常。
  • 第二次点击启动,未断开之前的绑定,timeout信号又新增1次绑定,此时计时器每秒触发时,槽函数会被执行2次,timecount每秒+2,视觉上表现为计时间隔“变长”(实际是数值跳变速度翻倍)。
  • 后续每点击一次启动,绑定次数就增加一次,槽函数执行次数同步增多,最终间隔“变长”的现象会越来越明显。

解决方法

以下三种方式任选其一即可:

1. 仅在初始化时绑定一次信号槽

把timeout信号的连接逻辑移到__init__方法中,避免重复绑定:

def __init__(self):
    # ... 其他初始化代码 ...
    self.timer.timeout.connect(self.startPressed)  # 移至初始化阶段
    self.button1.clicked.connect(self.start_timer)
    self.button2.clicked.connect(self.stop_timer)

def start_timer(self):
    self.timer.start(1000)
    self.timecount=0  # 移除重复的connect代码

2. 启动前先断开已有连接

在启动计时器前,先断开timeout与startPressed的连接,再重新绑定:

def start_timer(self):
    try:
        self.timer.timeout.disconnect(self.startPressed)
    except TypeError:
        pass  # 未连接时会抛出TypeError,直接忽略
    self.timer.timeout.connect(self.startPressed)
    self.timer.start(1000)
    self.timecount=0

3. 使用唯一连接标志

连接时添加QtCore.Qt.UniqueConnection标志,重复连接不会创建新的绑定:

def start_timer(self):
    self.timer.timeout.connect(self.startPressed, QtCore.Qt.UniqueConnection)
    self.timer.start(1000)
    self.timecount=0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:38:19