如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色? [英] How do I update the Color of a **dynamically added** Ellipse (not using Builder) according to Widget Kivy properties?

查看:17
本文介绍了如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与 其他问题.唯一的区别是我使用 with self.canvas 动态添加椭圆,而不是使用 Builder(Builder.load_stringBuilder.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)的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆