Search code examples
pythonkivy

Why isn't widgets in the BoxLayout laid out correctly when only using Python?


I am trying to get my head around Kivy and was playing with making some Widgets in Python, to make the structure of the kv file a bit lighter.

I have created a small compound widget, with a BoxLayout containing a label, and another label between two buttons.

To my confusion if I add this code by itself, the layout is placed at 0,0 with sizes 100,100. So it doesn't look like the layout is performed at all. While adding another widget through a .kv file/string the layout is done.

I assume this is not a bug, but that I am missing something in how kivy works. My question is how can I get the layout without having to add an extra widget through a .kv file?

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
kivy.require('2.1.0') 

class Example(App):
    def build(self):
        return Spinner()

class Spinner(BoxLayout):
    def __init__(self, **kwargs):
        # make sure we aren't overriding any important functionality
        super(BoxLayout, self).__init__(**kwargs)
        self.orientation = "horizontal"
        label = Label(text="Counting very long", size_hint=(0.5, None))
        lower = Button(text="-", size_hint=(0.1, None))
        number = Label(text="1", size_hint=(0.2, None))
        higher = Button(text="+", size_hint=(0.1, None))
        self.add_widget(label)
        self.add_widget(lower)
        self.add_widget(number)
        self.add_widget(higher)

#If we do not add this, no layout is done
Builder.load_string("""
<Spinner>:
   Label:
      text: "Wow, now it works"
      size_hint: (0.1, None)
""")
        
if __name__ == "__main__":
    Example().run()


Solution

  • In your __init__() method you should be calling the super method of your Spinner class, but you are skipping that and calling the super method of BoxLayout. Just change:

    super(BoxLayout, self).__init__(**kwargs)
    

    to:

    super(Spinner, self).__init__(**kwargs)