Search code examples
pythonkivy

Drawing line at init method with widget relative coordinates


I need to draw a line inside a Widget. But I've seen that the relative position and size of the widget aren't setted until the init method finish.

How can I draw a graphic element inside a widget with his relative position and dimension while I instantiate the class? (I would like to avoid Kv lang)

class Track(Widget):

    def __init__(self,**kw):
        super(Track, self).__init__(**kw)
        with self.canvas:
            Color(1,0,0)
            Line(points = (self.x, (self.y + self.height) / 2, self.x + self.width,  (self.y + self.height) / 2))

In this way the line it's drawn using the initial size and position which are 100,100 and 0,0 but the Widget it's inside a Layout so I'd like to use the relative position and size and I'd like to drawn it in the init


Solution

  • I would like to avoid Kv lang

    I recommend discarding this restriction.

    In this way the line it's drawn using the initial size and position which are 100,100 and 0,0 but the Widget it's inside a Layout so I'd like to use the relative position and size and I'd like to drawn it in the init

    You have three options. The first is to draw it in a clock (kivy.clock.Clock) scheduled function that runs after the widget has been positioned - it should be sufficient to do Clock.schedule_once(the_func, 0), with the 0 deferring the calculation to after the widget is positioned (assuming a normal layout) but before the next frame. The downside is that the line will then be fixed, and won't match the widget if if ever moves, e.g. potentially during window resize.

    The second (and better) option is to draw the line as you are now, but bind to the widget pos and size a function that repositions it appropriately. e.g. self.bind(pos=self.line_setter, size=self.line_setter) and have self.line_setter be a method with self.line.points = [...] as appropriate. You would also need to save a reference to the line with self.line = Line(...).

    The third (and normally best) option is to use kv language, which automatically creates the bindings for you with no additional syntax.