Kivy应用开发求助:切换Widget时触发AttributeError错误
解决Kivy替换部件时的AttributeError问题
我正在用Kivy开发一款趣味手机应用,这是我的首个大型编程项目。现在遇到功能瓶颈:通过climbtype函数的输出值触发条件判断,想把"grade"部件替换为Sport_Spinner_widget,但每次尝试都会抛出以下错误:
File "kivy\properties.pyx", line 964, in kivy.properties.ObservableDict.__getattr__ AttributeError: 'super' object has no attribute '__getattr__'. Did you mean: '__setattr__'?
确定问题出在add_sport_grades方法的目标代码里,尝试过改用LogClimb类中可行的self.ids.container.add_widget(customewidget)路径,但没用。
相关代码
.py文件
from kivy import Config from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.uix.screenmanager import ScreenManager, Screen class ClimbWidget(BoxLayout): def remove(self): self.parent.remove_widget(self) def climbtype(self, value): if value == "Sport": self.add_sport_grades() def add_sport_grades(self): customewidget = ClimbWidget() sportspinner = Sport_Spinner_widget() self.ids.grade.add_widget(sportspinner) # still not functioning?????!!! class LogClimb(Screen): def add_climb_inputs(self): customewidget = ClimbWidget() self.ids.container.add_widget(customewidget) class WindowManager(ScreenManager): pass kv = Builder.load_file("LogBook.kv") class LogBook(App): def build(self): return kv LogBook().run()
.kv文件
LogClimb: <LogClimb>: name: "LogClimb" BoxLayout: size_hint_y: 0.1 pos_hint: {"y" : 0.9} Label: text: "log Climb" Button: text: "Add Climb" on_press: root.add_climb_inputs() GridLayout: cols: 1 size_hint_y: 0.9 size_hint_x: 2 id: container <ClimbWidget> height: 40 size_hint_y: None Label: text: "date" Spinner: id: climbtype text: "Climb type" values: ["Sport", "Boldering", "Trad"] on_text: root.climbtype(climbtype.text) TextInput: id: climbvenu text: "Venue" font_size: "20dp" multiline: True #on_text_validate: root.on_text_validate(self) Spinner: id: "grade" text: "grade" font_size: "20dp" Button: text: "-" on_press: root.remove() <Sport_Spinner_widget>: height: 40 size_hint_y: None Spinner: text: "hi" values: ["1", "2", "2+", "3a", "3b", "3c", "4a", "4b", "4c", "5a", "5b", "5c", "5c", "6a", "6a+"]
解决方案
错误根源及修复要点
kv文件中id的引号错误
Kivy中控件的id不需要加引号,你写的id: "grade"会导致self.ids.grade无法找到对应部件,正确写法是id: grade。未定义自定义部件类
Python代码中缺少Sport_Spinner_widget类的定义,Kivy无法识别这个自定义部件,需要补充类定义。替换部件的逻辑错误
Spinner是单个控件,不能添加子部件。正确逻辑是先移除原有的grade Spinner,再将自定义部件添加到ClimbWidget的布局中。
修改后的代码
.py文件
from kivy import Config from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.uix.screenmanager import ScreenManager, Screen # 补充自定义部件类定义 class Sport_Spinner_widget(BoxLayout): pass class ClimbWidget(BoxLayout): def remove(self): self.parent.remove_widget(self) def climbtype(self, value): if value == "Sport": self.add_sport_grades() def add_sport_grades(self): # 移除原grade Spinner original_grade = self.ids.grade self.remove_widget(original_grade) # 创建并添加自定义部件 sportspinner = Sport_Spinner_widget() self.add_widget(sportspinner) class LogClimb(Screen): def add_climb_inputs(self): customewidget = ClimbWidget() self.ids.container.add_widget(customewidget) # 修正WindowManager的缩进(原代码嵌套在LogClimb中,会导致问题) class WindowManager(ScreenManager): pass kv = Builder.load_file("LogBook.kv") class LogBook(App): def build(self): return kv LogBook().run()
.kv文件
LogClimb: <LogClimb>: name: "LogClimb" BoxLayout: size_hint_y: 0.1 pos_hint: {"y" : 0.9} Label: text: "log Climb" Button: text: "Add Climb" on_press: root.add_climb_inputs() GridLayout: cols: 1 size_hint_y: 0.9 size_hint_x: 2 id: container <ClimbWidget> height: 40 size_hint_y: None orientation: 'horizontal' # 明确布局方向,确保部件排列一致 Label: text: "date" Spinner: id: climbtype text: "Climb type" values: ["Sport", "Boldering", "Trad"] on_text: root.climbtype(climbtype.text) TextInput: id: climbvenu text: "Venue" font_size: "20dp" multiline: True #on_text_validate: root.on_text_validate(self) Spinner: id: grade # 去掉引号 text: "grade" font_size: "20dp" Button: text: "-" on_press: root.remove() <Sport_Spinner_widget>: height: 40 size_hint_y: None Spinner: text: "hi" values: ["1", "2", "2+", "3a", "3b", "3c", "4a", "4b", "4c", "5a", "5b", "5c", "5c", "6a", "6a+"]
额外修正:原代码中WindowManager类嵌套在LogClimb类内部,这会导致ScreenManager无法正常工作,已调整为独立类。
内容的提问来源于stack exchange,提问作者Sam eldridge Darkfox
相关产品推荐
相关产品推荐

