如何根据Widget Kivy属性更新“动态添加的"椭圆(不使用Builder)的颜色? [英] How do I update the Color of a **dynamically added** Ellipse (not using Builder) according to Widget Kivy properties?
问题描述
self.bind(r=self.redraw)
self.bind(pos=self.redraw)
self.bind(size=self.redraw)
然后移动
with s.canvas:
Color(s.r,1,1,1)
Ellipse(pos = s.pos, size = s.size)
加入名为redraw
的方法,在此之前先进行self.canvas.clear()调用.
完整结果:
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()
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?
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()
这篇关于如何根据Widget Kivy属性更新“动态添加的"椭圆(不使用Builder)的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!