2013-03-19 139 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 
<:#}#:>