Search code examples
python-3.xbuttoncanvaskivykivymd

Why is my code for drawing a Line on a Layout's canvas not working?


I have this relatively simple and straightforward code that should draw a line using Kivy and Python.

This is the kv:

#:import Window kivy.core.window.Window

MDScreenManager:
    BigScreen:

<BigScreen>:
    name: "page"

    # layout holding cards
    MDFloatLayout:
        id: game_layout
        pos_hint: {'center_x': .5, 'center_y': .5}
        size_hint: None, None
        size: Window.width, Window.height
        md_bg_color: "black"

        MDIconButton:
            id: hint
            icon: "language-python"
            pos_hint: {"center_x": .5, "y": .9}
            theme_icon_color: "Custom"
            icon_color: "orange"
            md_bg_color: "white"
            on_release:
                app.draw_line()

And this is the origin Python file:

class BigScreen(MDScreen):
    pass

class DrawingApp(MDApp):

    def build(self):
        return Builder.load_string(kv)

    def draw_line(self):
        game_layout = self.root.get_screen("page").ids.game_layout

        with game_layout.canvas:
            Line(
                points = [0, 0, 700, 1000], 
                width = 10,
                color = (1, 0, 0),
            )

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

While a Line is being drawn on the layout every time I press on the button, it disappears after a short while.

Why is that?


Solution

  • Not sure why that line is disappearing, but you can fix it by adding the line in the kv, like this:

    MDFloatLayout:
        id: game_layout
        pos_hint: {'center_x': .5, 'center_y': .5}
        size_hint: None, None
        size: Window.width, Window.height
        md_bg_color: "black"
        line_color: 1, 0, 0, 0  # opacity is 0 (invisible)
        canvas:
            Color:
                rgba: self.line_color
            Line:
                width: 10
                points: [0, 0, 700, 1000]
    

    And then you can modify the draw_line() to simply change the line_color property (changing the opacity):

    def draw_line(self):
        game_layout = self.root.get_screen("page").ids.game_layout
        game_layout.line_color = 1,0,0,1  # note opacity change
    

    Note that you can use the same strategy to allow changing of the line width and/or line points by creating properties for them.