¿Cómo cambio el color de mi widget en Kivy en tiempo de ejecución?

Tengo problemas para cambiar el color de un widget simple en Kivy. Puedo configurar el color cuando creo el widget, pero no puedo cambiarlo después.

Aquí está el archivo de definición de diseño simple circletest.kv . Define un círculo donde el color (en realidad solo la r, de rgba), la posición y el tamaño están vinculados a las variables en la clase de widget.

 #:kivy 1.4.1 : canvas: Color: rgba: self.r,1,1,1 Ellipse: pos: self.pos size: self.size 

Aquí está la aplicación circletest.py . Crea y muestra el widget simple. El color y la posición se establecen correctamente cuando se crea el objeto. Cuando se hace clic en el widget, el widget puede cambiar su propia posición, pero cuando bash cambiar el color, no sucede nada.

 import kivy kivy.require('1.4.1') from kivy.app import App from kivy.lang import Builder from kivy.uix.widget import Widget Builder.load_file('circletest.kv') class CircleWidget(Widget): def __init__(s, **kwargs): s.size= [50,50] s.pos = [100,50] sr = 0 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 sr = 1.0 # <---- This does nothing! class TestApp(App): def build(s): parent = Widget() w = CircleWidget() parent.add_widget(w) return parent if __name__ == '__main__': TestApp().run() 

¿Alguien puede ver el problema?

ACTUALIZAR

Aún no estoy seguro de cuál es la respuesta a esta pregunta, pero tengo una solución:

En el archivo .kv señalé el color a una variable en mi objeto. Trabajos para extraer el color inicial:

 Color: rgba: self.col 

Cuando quiero cambiar el color del archivo .py, recorro todas las instrucciones del canvas y modifico la primera de tipo “Color”. Obviamente, esto es un truco y no funcionará en widgets con más de una propiedad Color: :

 for i in s.canvas.get_group(None): if type(i) is Color: ir, ig, ib, ia = v break 

Envolví todo eso en una propiedad, así que es fácil de usar:

 class CircleWidget(Widget): def get_col(s): return s._col def set_col(s,v): for i in s.canvas.get_group(None): if type(i) is Color: ir, ig, ib, ia = v break s._col = v col = property(get_col, set_col) def __init__(s, **kwargs): s.size= [50,50] s.pos = [100,50] s._col = (1,1,0,1) super(CircleWidget, s).__init__(**kwargs) def on_touch_down(s, touch): if s.collide_point(touch.x,touch.y): s.col = (s.col[::-1]) # Set to some other color 

Parece que funciona por ahora. Por favor, avíseme si conoce una mejor manera de hacer esto. Estoy seguro de que debe haber una forma más simple, y de que me estoy perdiendo algo obvio!

En su versión inicial, le faltaba la statement de la propiedad.

 from kivy.properties import NumericProperty 

en el encabezado y

 r = NumericProperty(0) 

justo debajo de la class CircleWidget(Widget):

también, indica que su archivo kv se llama circletest.kv, pero su aplicación se llama TestApp, por lo que debe cambiar uno de ellos para hacerlos coherentes, o no se encontrará su archivo kv, pero como no informa cualquier problema con eso, supongo que es solo un error tipográfico en la pregunta. edición: acabo de ver el Builder.load_file ok,

aclamaciones.

La respuesta de tshirtman es correcta, aquí está la explicación de lo que está pasando.

En tu archivo kv cuando configures

 : canvas: Color: rgba: self.r, 1, 1, 1 Ellipse: pos: self.pos size: self.size 

La línea rgba: self.r, 1, 1, 1 intenta actualizar el valor de rgba siempre que haya un cambio en el valor de r . Esto se hace implícitamente en el lenguaje kv mediante el enlace, lo que se puede hacer en una propiedad kivy cuando implementa un patrón de observador .

La variable r en su código se actualizó, pero es solo una variable que no proporciona ninguna indicación de que su valor haya cambiado y no pueda vincularse. Si observa sus cambios en pos trabajo porque pos es una pos referencia de lista.

Regla general para la progtwigción en Kivy, si desea cambiar el código en función de una propiedad de un Widget / Objeto, use una Propiedad Kivy . Le brinda la opción de observar los cambios de propiedad y ajustar su código en forma explícita a través de los eventos bind / on_property_name o implícitamente mediante el lenguaje kv como se mencionó anteriormente.