Reputation: 7715
I'm trying to create a template for a layout which looks like the following:
|----------|
| |
| IMAGE | <--- Just an image (square)
| |
|----------|
|[btn][btn]| <--- GridLayout cols=2 of buttons
|[btn][btn]|
|[btn][btn]|
|[btn][btn]|
|[btn][btn]|
|[btn][btn]|
|----------|
the first part is easy (but I could be wrong, as I'm very new at kivy)
#:kivy 1.6
[SideBar@BoxLayout]:
orientation: 'vertical'
Image:
source: ctx.image
size_hint: (1, None)
height: root.width
GridLayout:
cols: 2
# What do I do here to make it easy to load a list of buttons?
Upvotes: 3
Views: 11271
Reputation: 12935
Give a try to python-micro-template(https://github.com/diyism/python-micro-template), you could load the remote dynamic template file:
<:for i in range(30):#{#:>
Button:
text: '<:=i:><:for j in range(6):#{#:><:=j:><:#}#:>'
size: 480, 40
size_hint: None, None
<:#}#:>
Upvotes: 0
Reputation: 4162
#!/usr/bin/env python2
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
Builder.load_string('''
#:kivy 1.6
[SideBar@BoxLayout]:
content: content
orientation: 'vertical'
size_hint: ctx.size_hint if hasattr(ctx, 'size_hint') else (1, 1)
Image:
source: ctx.image
size_hint: (1, None)
height: root.width
GridLayout:
cols: 2
# just add a id that can be accessed later on
id: content
<Root>:
Button:
center_x: root.center_x
text: 'press to add_widgets'
size_hint: .2, .2
on_press:
# what comes after `:` is basically normal python code
sb.content.clear_widgets()
# however using a callback that you can control in python
# gives you more control
root.load_content(sb.content)
SideBar:
id: sb
size_hint: .2, 1
image: 'data/images/image-loading.gif'
''')
class Root(FloatLayout):
def load_content(self, content):
for but in range(20):
content.add_widget(Button(
text=str(but)))
class MyApp(App):
def build(self):
return Root()
if __name__ == '__main__':
MyApp().run()
I hope the inline comments make the example clear enough. In this case we are just passing the ref of the content to the function that adds widgets to the content.
There are situations where you might want to have access to the Widget as a attribute of your own class. In that case you can Use the following method.
The method above basically adds a ObjectProperty of the same name as the id, passes the reference of the widget referenced to by the id to it. So you, now have a attribute with the same name as the id in your python class for easy access. Using the above mentioned method your code would look something like this.
#!/usr/bin/env python2
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
Builder.load_string('''
#:kivy 1.6
[SideBar@BoxLayout]:
content: content
orientation: 'vertical'
size_hint: ctx.size_hint if hasattr(ctx, 'size_hint') else (1, 1)
Image:
source: ctx.image
size_hint: (1, None)
height: root.width
GridLayout:
cols: 2
# just add a id that can be accessed later on
id: content
<Root>:
content: sb.content
Button:
center_x: root.center_x
text: 'press to add_widgets'
size_hint: .2, .2
on_press:
sb.content.clear_widgets()
root.load_content()
SideBar:
id: sb
size_hint: .2, 1
image: 'data/images/image-loading.gif'
''')
class Root(FloatLayout):
content = ObjectProperty(None)
'''This is initialised to None and in kv code at line 28
above (the one with `content: sb.content`) a ref to the
actual content is passed'''
def load_content(self):
content = self.content
for but in range(20):
content.add_widget(Button(
text=str(but)))
class MyApp(App):
def build(self):
return Root()
if __name__ == '__main__':
MyApp().run()
Upvotes: 10