Search code examples
pythonpython-3.xcanvaskivykivy-language

Python Kivy - Issue moving canvas objects


After running different aspects on trying to update an item within the canvas. The objects refuse to move within the canvas, even if I have the reference to the object itself I cannot set its position. The portion of the code I am providing here seems to be the only real issue. It runs through the Screen getting a widget and the widget contains a canvas along with labels. I am able to go through the labels without issue and same with the canvas objects. Only difference being that I cannot reposition the canvas objects but I have zero issue with the labels.

Is there a special attribute or method to update or change the canvas objects positions? I have tried using ask_update(), draw(), flagging the object moved and etc. I am not sure as to why it does not work.

         if type(obj).__name__ == DonateButton.__name__:
            cnv_items = [child for child in obj.canvas.children]
            for cnv_obj in cnv_items:
                if type(cnv_obj).__name__ in [Ellipse.__name__, RoundedRectangle.__name__]:
                    cnv_obj.pos = (0,0)

Solution

  • You can use group instructions of canvas to change the attributes of its objects on the fly. Below is an example showing Rectangle and Ellipse objects under one canvas with changing pos attribute with randomly generated numbers:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.clock import Clock
    from kivy.uix.boxlayout import BoxLayout
    from kivy.core.window import Window
    import random
    
    APP_KV = """
    <CanvasTest>:
        canvas:
            Color:
                rgba: 0, 1, 0, 1
            Rectangle:
                group: 'rectangle'
                size: 400, 200
                pos: self.pos
            Color:
                rgba: 1, 0, 0, 1
            Ellipse:
                group: 'ellipse'
                size: 200, 100
                pos: self.pos
    """
    
    class CanvasTest(BoxLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            Clock.schedule_interval(self.test_pos, 1)
            
        def test_pos(self, *args):
            self.canvas.get_group('rectangle')[0].pos = random.randrange(1, Window.width - 400), random.randrange(1, Window.height - 200)
            self.canvas.get_group('ellipse')[0].pos = random.randrange(1, Window.width - 200), random.randrange(1, Window.height - 100)
    
    class MainApp(App):
        def build(self):
            self.root = Builder.load_string(APP_KV)
            return CanvasTest()
    
    if __name__ == '__main__':
        MainApp().run()