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

Kivy多屏幕开发报AttributeError: 'super'对象无__getattr__属性如何解决

报错原因

Kivy 组件的 id 存在作用域限制:

  • 每个组件声明的 id 仅会被收录到它的直属父级所在的根组件的ids字典中,不会向上穿透到更上层的组件节点
  • 多屏幕版本中,ball 这个 id 是定义在 <GameScreen> 组件内部的,因此它只存在于 GameScreen 实例的ids字典里
  • 你当前App的根节点是main.kv中声明的GridLayout,它的ids字典里只有screen_manager这一个id,调用self.root.ids.ball自然找不到对应组件,因此抛出AttributeError
  • 无多屏幕版本可以正常运行,是因为ball的id直接定义在App根布局的ids字典中,调用路径完全匹配
修复方案

仅需要调整move_ball方法中获取ball实例的逻辑即可,提供两种可行实现:

方法1:直接通过ScreenManager获取GameScreen实例再取值

修改main.py中的move_ball方法:

def move_ball(self, time_passed):
    # 先取屏幕管理器,再拿到游戏屏幕实例,最后从游戏屏幕的ids中取ball
    game_screen = self.root.ids.screen_manager.get_screen("game_screen")
    ball = game_screen.ids.ball
    ball.y = ball.y + ball.velocity * time_passed
    ball.velocity = ball.velocity - self.GRAVITY * time_passed

方法2:提前缓存ball实例(适合高频调用场景,性能更好)

先修改change_screen方法,切换到游戏屏幕时就缓存ball实例:

def change_screen(self, screen_name):
    screen_manager = self.root.ids['screen_manager']
    screen_manager.current = screen_name
    # 切换到游戏屏幕时缓存ball实例
    if screen_name == "game_screen":
        self.game_ball = screen_manager.get_screen("game_screen").ids.ball

再修改move_ball方法直接使用缓存的实例:

def move_ball(self, time_passed):
    self.game_ball.y = self.game_ball.y + self.game_ball.velocity * time_passed
    self.game_ball.velocity = self.game_ball.velocity - self.GRAVITY * time_passed

额外提示:你当前HomeScreen类中加载并播放背景音的代码直接写在了类作用域下,会在类定义阶段就执行,建议调整到HomeScreen的on_enter生命周期方法中,避免出现重复加载、页面未加载就播放声音的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:15:11