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

使用Kivy.clock开发应用内Tracker模块秒表时触发Attribute Error问题求助

解决Tracker模块的AttributeError及定时器逻辑问题

首先来说你遇到的AttributeError:你在代码里用self.root.ids去访问start_stop_btn、sec_ones这些控件,但这些控件是定义在Tracker这个Screen内部的,self.root指向的是你的App根容器(一般是ScreenManager),它根本没有这些id,所以应该改成self.ids来访问当前Screen内的控件——这就是触发错误的核心原因。

除了这个错误,你的定时器逻辑还有两个致命问题,会导致程序异常甚至卡死:

  • 每次点击Start按钮都会重复调用Clock.schedule_interval,这会让多个定时器同时运行,时间会被无意义地加速;
  • add_time里的while self.start循环会阻塞Kivy的主线程,Kivy是单线程框架,这个循环会让UI完全无法更新,也无法响应其他操作。

下面是修复后的完整代码:

修复后的Python代码

from kivy.uix.screenmanager import Screen
from kivy.clock import Clock

class Tracker(Screen):
    time = 0
    start = False
    timer_event = None  # 用来保存定时器事件,方便后续取消

    def start_stop(self):
        self.start = not self.start
        self.ids.start_stop_btn.text = 'Stop' if self.start else 'Start'

        if self.start:
            # 仅在启动时调度定时器,每秒执行一次add_time
            self.timer_event = Clock.schedule_interval(self.add_time, 1)
        else:
            # 停止时取消定时器,避免重复调度
            if self.timer_event:
                self.timer_event.cancel()
                self.timer_event = None

    def add_time(self, *args):
        # 因为定时器每秒自动调用一次,所以不需要while循环,每次执行一次时间递增逻辑即可
        sec_ones = int(self.ids.sec_ones.text) + 1
        sec_tens = int(self.ids.sec_tens.text)
        minute_ones = int(self.ids.minute_ones.text)
        minute_tens = int(self.ids.minute_tens.text)

        if sec_ones == 10:
            sec_ones = 0
            sec_tens += 1
            if sec_tens == 6:
                sec_tens = 0
                minute_ones += 1
                if minute_ones == 10:
                    minute_ones = 0
                    minute_tens += 1

        # 更新UI显示
        self.ids.sec_ones.text = str(sec_ones)
        self.ids.sec_tens.text = str(sec_tens)
        self.ids.minute_ones.text = str(minute_ones)
        self.ids.minute_tens.text = str(minute_tens)

        self.time += 1
        print(f"总时长:{self.time}秒")

对应的kv代码(无需修改)

<Tracker>:
    name: "Tracker"
    Label:
        text: "Timer: "
        font_size: 50
        pos_hint: {'x': 0.1, 'top': 1}
        size_hint: 0.2, 0.2
    Label:
        id: minute_tens
        text: '0'
        pos_hint: {'x': 0.36, 'top': 0.99}
        font_size: 40
        size_hint: 0.1, 0.2
        canvas.before:
            Color:
                rgba: (0.349, 0.349, 0.349, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        id: minute_ones
        text: '0'
        pos_hint: {'x': 0.47, 'top': 0.99}
        font_size: 40
        size_hint: 0.1, 0.2
        canvas.before:
            Color:
                rgba: (0.349, 0.349, 0.349, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        text: ':'
        pos_hint: {'x': 0.59, 'top': 0.99}
        font_size: 40
        size_hint: 0.05, 0.2
    Label:
        id: sec_tens
        text: '0'
        pos_hint: {'x': 0.65, 'top': 0.99}
        font_size: 40
        size_hint: 0.1, 0.2
        canvas.before:
            Color:
                rgba: (0.349, 0.349, 0.349, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        id: sec_ones
        text: '0'
        pos_hint: {'x': 0.76, 'top': 0.99}
        font_size: 40
        size_hint: 0.1, 0.2
        canvas.before:
            Color:
                rgba: (0.349, 0.349, 0.349, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    Button:
        id: start_stop_btn
        text: 'Start'
        pos_hint: {'x': 0.6, 'top': 0.77}
        size_hint: 0.1, 0.06
        on_release: root.start_stop()
    SmoothButton:
        text: "Back"
        pos_hint: {'x': 0.8, 'top': 0.15}
        size_hint: 0.15, 0.05
        on_release:
            app.root.current = "HomePage"
            root.manager.transition.direction = "right"

修复要点说明:

  1. 把所有self.root.ids替换成self.ids,正确访问当前Screen内的控件;
  2. 新增timer_event变量保存定时器事件,点击Stop时取消调度,避免重复启动多个定时器;
  3. 移除add_time里的while循环,利用Clock.schedule_interval的特性每秒自动执行一次时间递增逻辑;
  4. 重构时间递增的逻辑,用变量先存储数值,计算完成后再统一更新UI,代码更清晰易维护。

这样修改后,点击Start按钮就不会再触发AttributeError,定时器也能正常工作,UI也不会卡死了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:42:32