UPDATED WITH MORE EXAMPLE CODE
I have a test application which contains an Accordion. I want to be able to add items to the Accordion from within my python code.
Here is the kv code:
#: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
Using this layout, my application can display the Accordion, as well as the two sample AccordionItems shown above.
In my Python code, I somehow need to access the Accordion in order to add widgets to it. Here's my code which doesn't work:
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()
When I run the Python code above, I get an error:
self.mainLayout.ids['accordyN'].add_widget(entry) '~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^ KeyError: 'accordyN'
How do I add more kv widgets to the layout from my Python code?
The problem is that you are incorrectly trying to access the accordyN
id
. That id
is defined in the <ListView@BoxLayout>
rule, so it only appears in the ids
of the ListView
instance. But you also have have id
of r_list
that appears in the <LayoutTest>
rule, so that id
will appear in the ids
of the LayoutTest
instance, which is your root
of the widget tree. So you can access the accordyN
id by using the r_list
. Try replacing your line:
self.mainLayout.ids['accordyN'].add_widget(entry)
with:
self.mainLayout.ids.r_list.ids.accordyN.add_widget(entry)
This code uses the r_list
id
in the LayoutTest
instance to access the ListView
instance, and then uses its id
of accordyN
to access the Accordion
instance.