Skip to content Skip to sidebar Skip to footer

Nesting Widgets In Kivy

I'm trying to make an interface in kivy and I think there are some fundamental things I don't understand about custom widgets and how to hierarchy them, even after going through th

Solution 1:

The reason you get a blank screen is that your app's build() method does not return anything. Whatever it returns would be the root widget, but even though you make some widgets you don't return one so nothing is displayed.

If you fix this, you can run the app again but you'll immediately get an error something like MyApp has no attribute rect. This is because your root widget is immediately sized and positioned to fill the window, which (as per your root.bind line) triggers MyApp._update_rect. However, this method try to modify MyApp.rect.pos...but the app doesn't have a self.rect! You presumably intended to bind to root._update_rect, not the app's method. (Edit: I bound to root._update_rect instead and now at least the red background and green circle do appear.)

Edit: And as a side note, this would be a lot easier using the kv language, which could automatically take care of a lot of the widget creation, rectangle binding etc.

I don't have time to fix it all right now, but perhaps these two problems can help you fix the overall flow. I'll try to post a more complete answer later if nobody else has.


Here's an updated MyApp, as per the comments.

classMyApp(App):
    title = 'My App'defbuild(self):
        root = RootWidget()
        root.bind(
            size=root._update_rect,
            pos=root._update_rect)

Solution 2:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle, Ellipse


classMyApp(App):
    title = 'My App'defbuild(self):
        root = RootWidget()
        root.bind(
            size=root._update_rect,
            pos=root._update_rect)
        return root

classRootWidget(FloatLayout):
    def__init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        with self.canvas.before:
            Color(1, 0, 0, 1) # This RED does not display.
            self.rect = Rectangle(
                                    size=self.size,
                                    pos=self.pos,
                                    text="some junk!")  # This label does not display.
        mybackground = Background()
        self.add_widget(mybackground)
    def_update_rect(self, instance, value):
        self.rect.pos = instance.pos
        self.rect.size = instance.size

classBackground(Widget):
    def__init__(self, **kwargs):
        super(Background, self).__init__(**kwargs)
        with self.canvas.before:    
            Color(1, 1, 1, 1)       # This WHITE does not display
            self.rect = Rectangle(
                                    size=self.size,
                                    pos=self.pos,
                                    text="More stuff!")  # This label does not display.
        myholder = Holder()
        self.add_widget(myholder)
    def_update_rect(self, instance, value):
        self.rect.pos = instance.pos
        self.rect.size = instance.size

classHolder(Widget):
    def__init__(self, **kwargs):
        super(Holder, self).__init__(**kwargs)
        with self.canvas.before:    
            Color(0.25, 0.25, 0.25, 1) # This GRAY does not display
            self.rect = Rectangle(
                                    size=self.size,
                                    pos=self.pos,
                                    text="More stuff!")  # This does not display.
        c1 = Circley(label="Label 1")  # I see I'd need to do some size/pos math here to center
        c2 = Circley(label="Label 2")  # but since everything isn't working, I've tabled this.
        self.add_widget(c1)
        self.add_widget(c2)
    def_update_rect(self, instance, value):
        self.rect.pos = instance.pos
        self.rect.size = instance.size
    defon_touch_down(self, touch):
        rcolor = Color(random(), random(), random(), 1)
        with self.canvas:
            self.color = rcolor

classCircley(Widget):
    def__init__(self, label='label', **kwargs):
        super(Circley, self).__init__(**kwargs)
        with self.canvas.before:    
            Color(0, 1, 0, 1) # This GREEN does not display
            self.circ = Ellipse(
                        size=self.size,
                        pos=self.pos,
                        text=label
            )
    def_update_circ(self, instance, value):
        self.circ.pos = instance.pos
        self.circ.size = instance.size
    defon_touch_down(self, touch):
        rcolor = Color(random(), random(), random(), 1)
        with self.canvas:
            self.color = rcolor

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

Post a Comment for "Nesting Widgets In Kivy"