Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I update the Color of a **dynamically added** Ellipse (not using Builder) according to Widget Kivy properties?

Tags:

kivy

This is very related to this other question. The only difference is that I am adding the Ellipse dynamically with with self.canvas instead of using the Builder (Builder.load_string or Builder.load_file). So here is the code that does work. When you click in the Ellipse it moves and change Color:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty
from kivy.graphics import Color, Ellipse

Builder.load_string("""
<CircleWidget>:
    canvas:
        Color:
            rgba: self.r,1,1,1
        Ellipse:
            pos: self.pos
            size: self.size
""")

class CircleWidget(Widget):
    r = NumericProperty(0)
    def __init__(s, **kwargs):
        s.size= [50,50]
        s.pos = [100,50]
        super(CircleWidget, s).__init__(**kwargs)

    def on_touch_down(s, touch):
        if s.collide_point(touch.x,touch.y):    
            s.pos = [s.pos[1],s.pos[0]]     # this works
            s.r = 1.0                       # this also works

class TestApp(App):
    def build(s):
        parent = Widget()
        parent.add_widget(CircleWidget())
        return parent

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

If I try to do the same without using the Builder, it doesn't work anymore:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty
from kivy.graphics import Color, Ellipse

class CircleWidget(Widget):
    r = NumericProperty(0)
    def __init__(s, **kwargs):
        s.size= [50,50]
        s.pos = [100,50]
        super(CircleWidget, s).__init__(**kwargs)
        with s.canvas:
            Color(s.r,1,1,1)
            Ellipse(pos = s.pos, size = s.size)

    def on_touch_down(s, touch):
        if s.collide_point(touch.x,touch.y):    
            s.pos = [s.pos[1],s.pos[0]]     # This doesn't work anymore
            s.r = 1.0                       # Neither do this

class TestApp(App):
    def build(s):
        parent = Widget()
        parent.add_widget(CircleWidget())
        return parent

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

The code runs and the event is actually called. More over, the Widget is moved (even if it is visually not clear) but the Instructions of the canvas are not updated.

Any ideas?

like image 986
toto_tico Avatar asked Jun 12 '13 05:06

toto_tico


1 Answers

The first version works because kv lang automatically bind the canvas recreation to properties in expressions, so these lines:

    Color:
        rgba: self.r,1,1,1

do more than this one:

    Color(s.r,1,1,1)

what you can do, howether, is to bind self.r to auto rebuild your canvas instructions.

in __init__

self.bind(r=self.redraw)
self.bind(pos=self.redraw)
self.bind(size=self.redraw)

and move the

    with s.canvas:
        Color(s.r,1,1,1)
        Ellipse(pos = s.pos, size = s.size)

Part to a method named redraw, with a self.canvas.clear() call before.

full result:

from kivy.app import App
from kivy.uix.widget import Widget

from kivy.properties import NumericProperty
from kivy.graphics import Color, Ellipse

class CircleWidget(Widget):
    r = NumericProperty(0)

    def __init__(s, **kwargs):
        super(CircleWidget, s).__init__(**kwargs)
        s.bind(r=s.redraw)
        s.bind(pos=s.redraw)
        s.bind(size=s.redraw)
        s.size = [50, 50]
        s.pos = [100, 50]

    def redraw(s, *args):
        s.canvas.clear()
        with s.canvas:
            Color(s.r, 1, 1, 1)
            Ellipse(pos = s.pos, size = s.size)

    def on_touch_down(s, touch):
        if s.collide_point(touch.x, touch.y):
            print "gotcha"
            s.pos = [s.pos[1], s.pos[0]]
            s.r = 1.0

class TestApp(App):
    def build(s):
        parent = Widget()
        parent.add_widget(CircleWidget())
        return parent

if __name__ == '__main__':
    TestApp().run()
like image 52
Tshirtman Avatar answered Oct 24 '22 16:10

Tshirtman