payala
payala

Reputation: 1397

Kivy custom widget not stacking

I have made an example layout with one custom widget called DTErrorBar,

<DTErrorBar>:
    RelativeLayout:
        size_hint: None, None
        size: 20, 450
        canvas:
            Color:
                rgba: col_fg
            Line:
                points: 10, 10, 10, 410
                width: 4
            Color:
                hsv: col_gn_marker_hsla
            Line:
                points: 10, 10, 10, 410
                width: 2

in my example, this widget contained in a BoxLayout like this:

    BoxLayout:
        orientation: "horizontal"
        DTErrorBar:
        Button:
        Button:
        DTErrorBar:

but I can't get it to stack with the buttons and the other DTErrorBar that are inside the boxLayout, this is what I'm getting:

enter image description here

And this what I would expect:

enter image description here

Now, you might ask, how did I get the image of what I expect?, It was made with a small change to the code where I use the custom widget:

    BoxLayout:
    orientation: "vertical"
    BoxLayout:
        orientation: "horizontal"
        RelativeLayout:
            DTErrorBar:
        Button:
        Button:
        RelativeLayout:
            DTErrorBar:

So, wrapping the DTErrorBar widget within a RelativeLayout seems to make it work, but I am not sure why, if I already have a RelativeLayout as a wrapper for everything inside my DTErrorBar widget.

In summary, what do I have to do to the definition of DTErrorBar to get the expected behavior? It would also be interesting if someone could explain what am I getting wrong here in order to learn from my mistake, thanks.

Full code for not-as-expected case: https://gist.github.com/payala/bc54f4d3d2378a97c26c9afe88858b07

Full code for not-as-expected case: https://gist.github.com/payala/9de4de166c7c1942cc923c32550bf661

Edit: Modification After jligeza's answer

In the python side, the DTErrorBar class was declared like this:

class DTErrorBar(Widget):
    pass

Which was creating the custom widget derived from the base Widget class. Changing to inherit from a Layout class solved it:

class DTErrorBar(RelativeLayout):
    pass

By doing this, it also no longer makes sense to have a RelativeLayout inside the widget definition, since the widget is itself a RelativeLayout, so the final widget definition code becomes this:

<DTErrorBar>:
    size_hint: None, None
    size: 20, 450
    canvas:
        Color:
            rgba: col_fg
        Line:
            points: 10, 10, 10, 410
            width: 4
        Color:
            hsv: col_gn_marker_hsla
        Line:
            points: 10, 10, 10, 410
            width: 2

Upvotes: 0

Views: 149

Answers (1)

jligeza
jligeza

Reputation: 4703

The DTErrorBar should subclass some layout widget, for example a RelativeLayout. If you subclass a simple Widget, then it has no idea how to position its children (here: the relative layout with a canvas), so it sets all their positions to the window's [0, 0].

Upvotes: 3

Related Questions