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
相关产品推荐
相关产品推荐

