2013-03-19 84 views
3

我试图创建一个布局,看起来像一个模板如下:动态网格布局Kivy模板

|----------| 
|   | 
| IMAGE | <--- Just an image (square) 
|   | 
|----------| 
|[btn][btn]| <--- GridLayout cols=2 of buttons 
|[btn][btn]| 
|[btn][btn]| 
|[btn][btn]| 
|[btn][btn]| 
|[btn][btn]| 
|----------| 

,第一部分是容易的(但我可能是错的,因为我很在kivy新)

#:kivy 1.6 
[[email protected]]: 
    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? 

回答

9
#!/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 
[[email protected]]: 
    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() 

我希望内嵌批注,让这个例子不够清晰。在这种情况下,我们只是将内容的引用传递给为内容添加小部件的函数。

在某些情况下,您可能想要将Widget作为您自己班的属性进行访问。在这种情况下,您可以使用以下method

上面的方法基本上添加了一个与id相同名称的ObjectProperty,并将id引用的小部件的引用传递给它。所以你现在有一个与你的python类中的id同名的属性,以方便访问。使用上面提到的方法,你的代码看起来像这样。

#!/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 
[[email protected]]: 
    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() 
+1

谢谢,这是我见过的最好的书面答复之一。 – yarbelk 2013-03-21 04:36:59

0

试用一下蟒蛇微模板(https://github.com/diyism/python-micro-template),你可以加载远程的动态模板文件:

<:for i in range(30):#{#:> 
Button: 
    text: '<:=i:><:for j in range(6):#{#:><:=j:><:#}#:>' 
    size: 480, 40 
    size_hint: None, None 
<:#}#:>