2013-06-12 4 views
7

Это очень связано с this other question. Единственное отличие состоит в том, что я добавляю Ellipse динамически с with self.canvas вместо использования Builder (Builder.load_string или Builder.load_file). Итак, вот код , который действительно работает. При нажатии на эллипсе он движется и изменить цвет:Как обновить цвет динамически добавленного ** ** Эллипса (не используя Builder) в соответствии с свойствами Widget Kivy?

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, он больше не работает:

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

код выполняется и тому событие действительно называется. Более того, виджет перемещается (даже если он визуально не ясен), но инструкции холста не обновляются.

Любые идеи?

+0

Я также экспериментировать с 'ask_update' и это не сработало. –

+0

Мне нравится, когда вопрос, на который мне нужен ответ, почти дословно отвечает на stackoverflow :) – Nebelhom

ответ

8

Первая версия работает потому, что киловольт языки автоматически связываются брезентовый отдых к свойствам в выражениях, так что эти строки:

Color: 
     rgba: self.r,1,1,1 

сделать больше, чем это:

Color(s.r,1,1,1) 

что вы можете сделать, howether, это привязать self.r к автоматической перестройке ваших инструкций по холсту.

в __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() вызова ранее.

полный результат:

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

Большое спасибо! Я начинал подозревать, что Строитель делал что-то еще, а не просто разбирал язык Киви. –

+1

Ну, технически это часть разбора, это просто, что язык kv построен, чтобы сделать эти вещи проще простого python. Спасибо за бонус :). – Tshirtman