Python Kivy on_enter访问Screen控件报AttributeError问题
问题原因
你遇到的报错和self指向无关,核心是两处逻辑错误:
build()方法返回值错误:你在KV规则中已经定义了根组件为MyWinMan(ScreenManager子类,内部已挂载W_MainMenu、W_FileSelector两个屏幕实例),但在build()中手动返回了一个孤立的全新W_MainMenu()实例,这个实例既没有被ScreenManager管理,和KV中定义的W_MainMenu实例也不是同一个对象。- 事件触发时机不匹配:孤立的W_MainMenu实例不在ScreenManager管理链路中,触发
on_enter事件时,内部子控件(包括id为pgb_sql_read的进度条)还未完成初始化、未注册到ids字典,访问self.ids.pgb_sql_read自然会抛出属性不存在的错误,最终触发你看到的AttributeError: 'super' object has no attribute '__getattr__'异常。
标准实现步骤
1. 修正根组件返回逻辑
你当前代码中Builder.load_string()执行时已经创建了包含两个Screen的MyWinMan根实例,只是没有接收返回值。首先把加载KV的返回值存下来,修改App类的build方法直接返回这个正确的根实例,保证屏幕切换逻辑、事件生命周期正常触发,不要单独新建孤立的Screen或者ScreenManager实例:
# 加载KV时接收返回的根组件实例 root = Builder.load_string(""" # 你原有的KV内容完全保持不变即可 """) # 其他自定义类(MyWinMan、W_MainMenu、W_FileSelector)代码保持不变 class MyApp(App): def build(self): # 直接返回KV加载生成的根实例 return root
修正后你按钮中写的
app.root.current = "win_FS"屏幕切换逻辑也能正常工作,之前根组件为孤立W_MainMenu时,本身没有current属性,点击按钮也会报错。
2. 选择正确的控件初始化时机
要在界面显示前/显示后立即操作控件,有两种通用的标准写法,完全不会出现ids找不到的问题:
方案一(推荐,用于初始化控件默认状态):使用on_kv_post生命周期方法
on_kv_post会在当前Screen的KV规则加载完成、所有子控件初始化完毕、ids字典完全填充后触发,时机早于on_enter,最适合做控件初始状态设置(比如初始隐藏进度条):
class W_MainMenu(Screen): def on_kv_post(self, base_widget): # 此处访问ids100%不会出现找不到控件的问题 self.hide_widget(self.ids.pgb_sql_read, True) # 原有的hide_widget、transform_to_filechooser、import_to_sql方法保留即可 # 如果on_enter没有其他逻辑可以直接删除
方案二(用于入场动画类逻辑):on_enter搭配一帧延迟
如果确实需要在屏幕入场动画阶段操作控件,不要直接在on_enter里访问ids,加一个0延迟的时钟调度,等下一帧控件树完全渲染完成再执行:
# 先在文件头部导入Clock from kivy.clock import Clock class W_MainMenu(Screen): def on_enter(self): Clock.schedule_once(lambda dt: self.hide_widget(self.ids.pgb_sql_read, True), 0)
内容的提问来源于stack exchange,提问作者BlueHawk77
相关产品推荐
相关产品推荐

