kivy properties and canvas

259 views
Skip to first unread message

Damien Moore

unread,
Jul 21, 2014, 1:20:32 PM7/21/14
to kivy-...@googlegroups.com
Can someone tell me why this doesn't work:

https://gist.github.com/spillz/cb68aca4f4595d13a9fc

If i change my_rect_size to size it works just fine, so I guess it has something to do with the property being initialized after the first canvas call. If so, is that a bug? Or is there some other way to do these sorts of canvas calculations (the actual use case is more complex than this trivial example and so just moving the calculations to the rectangle is not desirable and would result in a lot of repetition)

ZenCODE

unread,
Jul 21, 2014, 2:38:16 PM7/21/14
to kivy-...@googlegroups.com
Greetings

Running the code as is, I get
     >>   10:            size: root.my_rect_sizea
     ...
     TypeError: 'NoneType' object is not iterable

You could also do it in Python, roughtly like this: http://kivy.org/docs/guide/graphics.html#manipulating-instructions

I think the problem is you need to either bind to these "on_pos" or "on_size" to handle more complex calculation. Here is a good reference:  http://kivy.org/docs/guide/widgets.html. But you seem to have most of it, so skip to the "Adding a background to layout" section. Is that not what you are looking for?

Cheers

Damien Moore

unread,
Jul 21, 2014, 3:59:01 PM7/21/14
to kivy-...@googlegroups.com
Thanks but was hoping to avoid doing it in python. An ugly workaround is the following:

Builder.load_string('''
#:kivy 1.6
<MyLayout>:
    my_rect_size: self.size[0]/2, self.size[1]/2
    canvas:
        Color:
            rgba: [0,1,0,1]
        Rectangle:
            pos: self.pos
            size: [0,0] if self.my_rect_size is None else self.my_rect_size
''')

And to make it readable I define a small helper function to catch an uninitialized value so instead of

            size: [0,0] if self.my_rect_size is None else self.my_rect_size

I can just write

          size: fn(self.my_rect_size)

And that works fine, which is what makes me wonder whether the current canvas behavior isn't just a bug...

ZenCODE

unread,
Jul 21, 2014, 4:21:48 PM7/21/14
to kivy-...@googlegroups.com
No, I don't think it's a bug. It's that the layout's do some event bubbling to determine the size of the children before doing the final layout logic. That means these "on_size" and "on_pos" events can be fired before the widgets size or position has really been finalized. It part of the magic of layout's.

So you've using kivy to do the binding for you, nice, more compact. I think your "fn" solution is probably the best. Given that you are adding logic, it makes clearly separated and DRY :-)

Damien Moore

unread,
Jul 22, 2014, 9:58:09 AM7/22/14
to kivy-...@googlegroups.com
I guess that makes sense. I have generally found the KV language makes graphical layouts simpler and more readable compared to python. It's a shame that python can't support a syntax like this directly -- it would be a boon to all python UI libraries.

Alexandre Lancar

unread,
Jul 22, 2014, 1:54:10 PM7/22/14
to kivy-...@googlegroups.com
i would do it like that

 
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ListProperty


Builder.load_string('''

#:kivy 1.6
<MyLayout>:
    my_rect_size: self.size[0]/2, self.size[1]/2
    canvas:
        Color:
            rgba: [0,1,0,1]
        Rectangle:
            pos: self.pos
            size: self.my_rect_size
'''
)


class MyLayout(FloatLayout):
    my_rect_size
=ListProperty([0,0])
   
def __init__(self,**kwargs):
       
super(MyLayout, self).__init__(**kwargs)


class MyApp(App):
   
def build(self):
       
return MyLayout()


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



ZenCODE

unread,
Jul 25, 2014, 4:53:00 PM7/25/14
to kivy-...@googlegroups.com
@Alexandre Lancar

Yes, spot on. Nice one ;-)
Reply all
Reply to author
Forward
0 new messages