问题描述
这与 其他问题.唯一的区别是我使用 with self.canvas
动态添加椭圆,而不是使用 Builder(Builder.load_string
或 Builder.load_file
).所以这里是可以工作的代码.当您单击椭圆时,它会移动并更改颜色:
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()
如果我尝试在不使用 Builder
的情况下做同样的事情,它就不再起作用了:
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()
代码运行,事件被实际调用.此外,Widget 被移动(即使它在视觉上不清晰)但画布的 Instructions 没有更新.
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.
有什么想法吗?
推荐答案
第一个版本可以工作,因为 kv lang 自动将画布重新绑定到表达式中的属性,所以这些行:
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
做更多的事情:
Color(s.r,1,1,1)
你可以做的就是绑定 self.r 来自动重建你的画布指令.
what you can do, howether, is to bind self.r to auto rebuild your canvas instructions.
在 __init__
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().
Part to a method named redraw
, with a self.canvas.clear() call before.
完整结果:
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)的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!