Guglie
Guglie

Reputation: 2441

Kivy nested BoxLayout stacks widgets on bottom left corner

I'm trying do dynamically build a Kivy layout with a vertical BoxLayout containing a varying number of custom MyRow widgets that can change at runtime. layout example each row is an horizontal BoxLayout

I'm not using a GridLayout because MyRow layout is being developed and can change in the near future adding widgets etc. like this example layout example 2

But with the code below I only get small widgets stacked on top of each other in the bottom left corner of the window.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty

class MyRow(Widget):
    a = StringProperty('a')
    b = StringProperty('b')

    def __init__(self, **kwargs):
        super(MyRow, self).__init__(**kwargs)

class MainScreen(Widget):

    rows = [['a1','b1'],['a2','b2']] #example data

    mainLayout = BoxLayout(orientation='vertical', spacing=5)

    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)

        self.add_widget(self.mainLayout)

        for r in self.rows:
            row_widget = MyRow()

            row_widget.a = r[0]
            row_widget.b = r[1]

            self.mainLayout.add_widget(row_widget)

class MyApp(App):

    def build(self):
        return MainScreen()

if __name__ == '__main__':
    MyApp().run()

and this is the kv file:

<MyRow>
    BoxLayout:
        orientation: "horizontal"
        spacing: 30
        Label:
            id: a_label
            text: root.a
        Label:
            id: b_label
            text: root.b

Upvotes: 1

Views: 2633

Answers (1)

PalimPalim
PalimPalim

Reputation: 3048

In your sketch it says MyRow is based on an horizontal BoxLayout. But it is not. It is build on widget

Simply changing

class MyRow(Widget):

to

class MyRow(BoxLayout):

will solve your problem.

enter image description here


To get spacing right or better I would update your code to the following

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.base import Builder



class MyRow(BoxLayout):
    a = StringProperty('a')
    b = StringProperty('b')

    def __init__(self, **kwargs):
        super(MyRow, self).__init__(**kwargs)

class MainScreen(BoxLayout):

    rows = [['a1','b1'],['a2','b2']]*5 

    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.orientation = "vertical"

        for r in self.rows:
            row_widget = MyRow()

            row_widget.a = r[0]
            row_widget.b = r[1]

            self.add_widget(row_widget)



class MyApp(App):

    def build(self):
        return MainScreen()

if __name__ == '__main__':
    MyApp().run()

and your kv

<MyRow>:
    orientation: "horizontal"
    spacing: 30
    Label:
        id: a_label
        text: root.a
    Label:
        id: b_label
        text: root.b

which gives you enter image description here


To inherit from a Boxlayot in python use class Row(BoxLayout): in kv file use <Row@BoxLayout>:

Upvotes: 6

Related Questions