【问题标题】:Kivy template with dynamic grid layout具有动态网格布局的 Kivy 模板
【发布时间】:2013-03-08 00:25:16
【问题描述】:

我正在尝试为布局创建一个模板,如下所示:

|----------|
|          | 
| 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
[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?

【问题讨论】:

    标签: python layout widget kivy


    【解决方案1】:
    #!/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()
    

    我希望内联 cmets 使示例足够清晰。在这种情况下,我们只是将内容的 ref 传递给将小部件添加到内容的函数。

    在某些情况下,您可能希望访问 Widget 作为您自己类的属性。在这种情况下,您可以使用以下method

    上面的方法基本上是加了一个与id同名的ObjectProperty,将id所引用的widget的引用传递给它。因此,您现在拥有一个与 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
    [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()
    

    【讨论】:

    • 谢谢,这是我见过的最好的书面回复之一。
    【解决方案2】:

    试试python-micro-template(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
    <:#}#:>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-20
      • 1970-01-01
      • 2018-10-24
      • 1970-01-01
      • 2018-05-22
      • 1970-01-01
      相关资源
      最近更新 更多