¿Cómo actualizo el Color de un ** ** agregado dinámicamente ** Elipse (sin usar Builder) de acuerdo con las propiedades de Widget Kivy?

Esto está muy relacionado conesta otra pregunta. La única diferencia es que estoy agregando la Elipse dinámicamente conwith self.canvas en lugar de utilizar el generadorBuilder.load_string oBuilder.load_file). Así que aquí está el códigoeso funciona. Cuando haces clic en el elipse se mueve y cambia de 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()

Si intento hacer lo mismo sin usar elBuilder, ya no funciona:

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()

El código se ejecuta y el evento se llama realmente. Además, el Widget se mueve (incluso si no está claro visualmente) pero las Instrucciones del lienzo no se actualizan.

¿Algunas ideas?

Respuestas a la pregunta(1)

Su respuesta a la pregunta