Search code examples
pythonkivykivy-language

Get canvas size and draw rectangle in Kivy


I would like to draw something in canvas from .py by using class 'BotRightCanvas'. The initial widgets are all defined in .kv

Problem is when I finally declare BotRightCanvas in .kv, the size of the canvas widget is not coming proper (still 100x100). I would like the green rectangle to coincide with the cyan one.

widgetPrint

Here's .py

from kivy.graphics import Color
from kivy.graphics.vertex_instructions import Line, Rectangle, Ellipse
from kivy.metrics import dp
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window


class TestOut(BoxLayout):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def getSize(self, id):
        cSize = id.size
        print('win ' + str(Window.size))
        print('canvas ' + str(id.size))
        print('cSize ' + str(cSize))


class BotRightCanvas(Widget):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        with self.canvas:
            Color(0, 1, 0, 1)
            Line(circle=(self.width / 2, self.height / 2, 25), width=2)
            Line(rectangle=(0, 0, self.width, self.height), width=5)


class PlaygroundApp(App):
    title = "blabla"

    def build(self):
        return TestOut()


if __name__ == "__main__":
    PlaygroundApp().run()

and .kv

<TestOut>:

    BoxLayout:
        orientation: 'vertical'
        Button:
            text:'A'
            height: dp(100)
            size_hint: 1, None
        BoxLayout:
            Button:
                text:'B'
                width: dp(150)
                size_hint: None, 1
            RelativeLayout:
                id: rel_lo
                on_size: root.getSize(rel_lo)
                Widget:
                    canvas:
                        Line:
                            rectangle: (0,0, self.width, self.height)
                            width: 2
                    canvas.before:
                        Color:
                            rgba: 0,1,1,1
                    BotRightCanvas:

I tried printing the final canvas shape in console, seems it initializes with size of 0x0 but later on gets correct size 650x500.

The console output

canvas [0.0, 0]
cSize [0.0, 0]
win (800, 600)
canvas [650.0, 500.0]
cSize [650.0, 500.0]

Any help? Thanks !!

EDIT: Would like to control canvas items from .py


Solution

  • from kivy.graphics import Color
    
    from kivy.graphics.vertex_instructions import Line, Rectangle, Ellipse
    
    from kivy.metrics import dp
    
    from kivy.uix.widget import Widget
    
    from kivy.uix.boxlayout import BoxLayout
    
    from kivy.core.window import Window
    
    from kivy.lang.builder import Builder
    
    from kivy.app import App
    
    class TestOut(BoxLayout):
    
    
    
        def __init__(self, **kwargs):
    
            super().__init__(**kwargs)
    
    
    
        def getSize(self, id):
    
            cSize = id.size
    
            print('win ' + str(Window.size))
    
            print('canvas ' + str(id.size))
    
            print('cSize ' + str(cSize))
    
    
    
    
    
    class BotRightCanvas(Widget):
    
        pass
    
            
    
    
    
    
    
    
    
    Builder.load_string(
    
    
    
        '''
    
    <BotRightCanvas>:
    
        canvas:
    
            Color:
    
                rgba:0, 1, 0, 1
    
            Line:
    
                circle:self.width / 2, self.height / 2, 25
    
                width:2
    
    
    
            Line:
    
                rectangle:0, 0, self.width, self.height
    
                width:5
    
    <TestOut>:
    
    
    
        BoxLayout:
    
            orientation: 'vertical'
    
            Button:
    
                text:'A'
    
                height: dp(100)
    
                size_hint: 1, None
    
            BoxLayout:
    
                Button:
    
                    text:'B'
    
                    width: dp(150)
    
                    size_hint: None, 1
    
                RelativeLayout:
    
                    id: rel_lo
    
                    on_size: root.getSize(rel_lo)
    
                    Widget:
    
                        canvas:
    
                            Line:
    
                                rectangle: (0,0, self.width, self.height)
    
                                width: 2
    
                        canvas.before:
    
                            Color:
    
                                rgba: 0,1,1,1
    
                        BotRightCanvas:
    
                            size:rel_lo.size
    
        
    
        
    
        '''
    
    
    
    
    
    )
    
    class PlaygroundApp(App):
    
        title = "blabla"
    
    
    
        def build(self):
    
            return TestOut()
    
    
    
    for line in open('2.py').readlines():
    
        print('    '+line)
    
    if __name__ == "__main__":
    
        PlaygroundApp().run()