如何通过Python代码向Kivy的Accordion添加AccordionItem?
问题描述
我开发了一个包含Accordion组件的测试应用,希望通过Python代码向Accordion中添加AccordionItem。以下是对应的kv代码和Python代码,但运行Python代码时出现KeyError: 'accordyN'错误,无法找到目标Accordion组件。请问如何通过Python代码向布局中添加kv组件?
kv代码
#:kivy 1.0.9 <LayoutTest>: BoxLayout: id: mainBox orientation: 'horizontal' padding: 4 spacing: 4 canvas: Color: rgba: 0, 0.2, 0.4, 1 # Blue-ish color Rectangle: pos: self.pos size: self.size # workBox BoxLayout: orientation: 'vertical' canvas: Color: rgba: 0.16, 0.11, 0, 1 # brownish color Rectangle: pos: self.pos size: self.size ListView: id: r_list orientation: 'vertical' [AccordionItemTitle@Label]: text: ' ' + ctx.title halign: 'left' valign: 'center' text_size: self.size normal_background: ctx.item.background_normal if ctx.item.collapse else ctx.item.background_selected disabled_background: ctx.item.background_disabled_normal if ctx.item.collapse else ctx.item.background_disabled_selected canvas.before: Color: rgba: self.disabled_color if self.disabled else self.color BorderImage: source: self.disabled_background if self.disabled else self.normal_background pos: self.pos size: self.size PushMatrix Translate: xy: self.center_x, self.center_y Rotate: angle: 90 if ctx.item.orientation == 'horizontal' else 0 axis: 0, 0, 1 Translate: xy: -self.center_x, -self.center_y canvas.after: PopMatrix <ListItem@AccordionItem>: title: '2024/12/20 22:00 <reference>' BoxLayout: orientation: 'vertical' Label: text: 'Type 1' text_size: self.width, None Label: text: 'Content 3' text_size: self.width, None <ListView@BoxLayout>: Accordion: id: accordyN orientation: 'vertical' AccordionItem: title: '2024/12/20 00:00 <reference>' BoxLayout: orientation: 'vertical' size_hint_y: None # height: self.minimum_height # height: type_label.height + content_label.height valign: 'top' Label: id: type_label text: 'Type 1' text_size: self.size halign: 'left' valign: 'top' Label: id: content_label text: 'Content 1' text_size: self.size halign: 'left' valign: 'top' AccordionItem: title: '2024/12/20 09:00 <reference>' BoxLayout: orientation: 'vertical' Label: text: 'Type 1' text_size: self.width, self.height Label: text: 'Content 2' text_size: self.width, self.height
Python代码
import kivy from kivy.app import App # below this kivy version you cannot use the app kivy.require('1.9.0') from kivy.uix.boxlayout import BoxLayout from kivy.uix.accordion import AccordionItem class LayoutTest(BoxLayout): temp = 0 class ListItem(AccordionItem): temp = 0 class LayoutTestApp(App): mainLayout = None def __init__(self, **kwargs): super().__init__() def build(self): self.mainLayout = LayoutTest() entry = ListItem(title='2024/12/20 22:00 <reference>') self.mainLayout.ids['accordyN'].add_widget(entry) return self.mainLayout if __name__ == '__main__': LayoutTestApp().run()
错误信息
self.mainLayout.ids['accordyN'].add_widget(entry)
'~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'accordyN'
解决方案
错误原因
accordyN这个id属于自定义ListView组件内部的Accordion,而self.mainLayout.ids只能直接访问LayoutTest根布局下的id(也就是mainBox和r_list)。你需要先获取到r_list这个ListView实例,再通过它的ids访问内部的accordyN。
另外注意kv文件开头的#:kivy 1.0.9和Python代码里的kivy.require('1.9.0')版本不一致,建议统一为同一版本(比如改成#:kivy 1.9.0),避免潜在兼容性问题。
修改后的Python代码
import kivy from kivy.app import App kivy.require('1.9.0') from kivy.uix.boxlayout import BoxLayout from kivy.uix.accordion import AccordionItem class LayoutTest(BoxLayout): temp = 0 class ListItem(AccordionItem): temp = 0 class LayoutTestApp(App): mainLayout = None def __init__(self, **kwargs): super().__init__() def build(self): self.mainLayout = LayoutTest() entry = ListItem(title='2024/12/20 22:00 <reference>') # 先获取ListView实例r_list,再访问其内部的accordyN self.mainLayout.ids['r_list'].ids['accordyN'].add_widget(entry) return self.mainLayout if __name__ == '__main__': LayoutTestApp().run()
额外说明
Kivy的id作用域是当前规则内部:
LayoutTest规则里的id(mainBox、r_list)只能通过LayoutTest实例的ids访问- 自定义
ListView规则里的id(accordyN)只能通过ListView实例的ids访问
所以必须按照布局层级逐层获取组件,才能找到目标id对应的控件。
内容的提问来源于stack exchange,提问作者Todd Hoatson
相关产品推荐
相关产品推荐

