【问题标题】:How can the parent widget position its child widgets?父小部件如何定位其子小部件?
【发布时间】:2013-07-28 13:08:27
【问题描述】:

我有一个名为 MainPage 的 Kivy Widget,它有一个子小部件。这些子小部件需要访问与其父级相同的消息调度程序(与 Kivy 的 EventDispatcher 无关):

class MainPage(Widget):
    def __init__(self, dispatcher):
        self.child = ChildWidget(dispatcher)
        self.add_widget(child1)

.kv 文件中,我定义了<ChildWidget> 的视觉属性,但我没有指定它在<MainPage> 中的位置。我想<MainPage> 指定它的孩子应该如何定位。这样的事情可能吗?

<ChildWidget>:
    ...

<MainPage>:
    self.child:
        pos: (10, 10)

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    假设 ChildWidget 仍然是 Kivy Widget(继承自 Widget 或其子类)。

    [使用kv的简单方法]

    如果你想让孩子控制它在它的父母中的位置,你可以这样做::

    <ChildWidget>
        pos:  (self.parent.x + 10, self.parent.y + 10) if self.parent else (100, 100)
    

    为了控制孩子们的位置,我们可以这样做::

    <MainPage>
        on_children:
            # reposition children
            root.reposition_children(args[1])
        on_size:
            # reposition children when parents size changes
            root.reposition_children(self.children)
        on_pos:
            # reposition children when widgets size changes
            root.reposition_children(self.children)
    

    在你的 .py 中

    class MainPage(Widget):
        ...
        ...
        def reposition_children(self, children):
            for child in children:
                child.pos = x, y
                child.size = d, e
    

    [更详细更完整的方式]

    您实际上似乎想要的是您的主小部件的行为类似于Layout。此链接指向还包括内联文档的代码。代码本身是一个抽象类,它为您提供了有关如何构建/设计布局的指南。

    您应该从Layout 类继承并在do_layout 中进行小部件定位,通过self.trigger_layout 调用它(这样小部件的定位会延迟到它们需要显示在屏幕上并触发之前确保每帧不会多次调用该函数)。

    您应该在bind trigger_layout 中使用children, size, pos... 之类的属性,以便在这些属性更改时重新触发do_layout

    【讨论】:

      【解决方案2】:

      如果您的定位目标不太复杂,RelativeLayout 可能就足够了。

      class MainPage(RelativeLayout):
          def __init__(self, dispatcher, **kwargs):
              super(MainPage, self).__init__(**kwargs)
              self.child = ChildWidget(dispatcher, pos=(10,10))
              self.add_widget(self.child)
      

      RelativeLayout(以及通常的任何布局——除了保持绝对定位的 FloatLayout)保持子级更新到父级的位置。所有的布局也是小部件,所以你应该是安全的。

      <ChildWidget>:
          size_hint: .1, .05
          text: "press me"
          on_press: self.parent.pos = (200,200)
      <MainPage>:
          pos: 400,400
      

      这是我尝试过的完整代码:

      from kivy.app import App
      from kivy.lang import Builder
      from kivy.uix.relativelayout import RelativeLayout
      from kivy.uix.button import Button
      
      Builder.load_string("""
      <ChildWidget>:
          size_hint: .1, .05
          text: "press me"
          on_press: self.parent.pos = (200,200)
      <MainPage>:
          pos: 400,400
      """)
      
      class Dispatcher():
          pass
      
      class ChildWidget(Button):
          def __init__(self, dispatcher, **kwargs):
              super(ChildWidget, self).__init__(**kwargs)
              self.dispatcher = dispatcher
      
      class MainPage(RelativeLayout):
          def __init__(self, dispatcher, **kwargs):
              super(MainPage, self).__init__(**kwargs)
              self.child = ChildWidget(dispatcher, pos=(10,10))
              self.add_widget(self.child)
      
      class TestApp(App):
          def build(self):
              dispatcher = Widget()
              return MainPage(dispatcher)
      
      if __name__ == '__main__':
          TestApp().run()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-24
        • 1970-01-01
        • 2020-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-22
        • 2019-09-14
        相关资源
        最近更新 更多