How does the parent widget position its child widgets?

advertisements

I have a Kivy Widget called MainPage that has a child widget. These child widget needs to have access to the same message dispatcher (has nothing to do with Kivy's EventDispatcher) as its parent:

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

Inside the .kv file I defined the visual properties of <ChildWidget>, but I have not specified its position inside <MainPage>. I would like <MainPage> to specify how its children are supposed to be positioned. Is something like this possible?

<ChildWidget>:
    ...

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


Assuming ChildWidget is still a Kivy Widget (inherited from Widget or a subclass of it).

[simple way using kv]

if you wanted the child to control where it is positioned inside it's parent you could do::

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

for controlling the children's position one could do::

<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)

in your .py

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

[More elaborate and complete way]

What you essentially seem to want is your Main Widget to behave like a Layout. This link is to the code which also includes the inline docs. The code itself is a abstract class that gives you a guide-line on how to structure/fashion your layout.

You should inherit from the Layout class and do your widget positioning in do_layout, call it through self.trigger_layout(this way positioning of the widgets is delayed till just before they need to be displayed on screen and trigger makes sure that the function is not called multiple times per frame).

You should bind trigger_layout with properties like children, size, pos... so that do_layout is re-triggered whenever these properties change.