2013-06-12 3 views
7

Dies ist sehr verwandt mit this other question. Der einzige Unterschied ist, dass ich die Ellipse dynamisch mit with self.canvas anstelle des Builders (Builder.load_string oder Builder.load_file) hinzufüge. Also hier ist der Code , der funktioniert. Wenn Sie auf der Ellipse es sich bewegt und die Farbe wechseln:Wie aktualisiere ich die Farbe einer ** dynamisch hinzugefügten ** Ellipse (ohne Builder) gemäß Widget Kivy Eigenschaften?

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

Wenn ich versuche, das gleiche zu tun, ohne die Builder zu verwenden, wird es nicht mehr funktioniert:

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

der Code ausgeführt wird und die Ereignis wird tatsächlich aufgerufen. Darüber hinaus wird das Widget verschoben (auch wenn es visuell nicht klar ist), aber die Anweisungen des Canvas werden nicht aktualisiert.

Irgendwelche Ideen?

+0

Ich experimentiere auch mit 'ask_update' und es hat nicht funktioniert. –

+0

Ich mag es, wenn eine Frage ich brauche eine Antwort für fast wörtlich beantwortet auf stackoverflow :) – Nebelhom

Antwort

8

Die erste Version funktioniert, weil kv lang automatisch die Leinwand Erholung Eigenschaften in Ausdrücken binden, so dass diese Linien:

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

mehr tun, als diese:

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

was Sie tun können, Howether, binden Sie self.r, um Ihre Canvas-Anweisungen automatisch neu zu erstellen.

in __init__

self.bind(r=self.redraw) 
self.bind(pos=self.redraw) 
self.bind(size=self.redraw) 

und den redraw, bevor sie mit einem self.canvas.clear() Aufruf genannt

with s.canvas: 
     Color(s.r,1,1,1) 
     Ellipse(pos = s.pos, size = s.size) 

Teil auf ein Verfahren bewegen.

vollständiges Ergebnis:

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

Vielen Dank! Ich begann zu vermuten, dass der Builder etwas anderes machte, als nur die Kivy-Sprache zu analysieren. –

+1

Nun, technisch ist es Teil des Parsings, es ist nur so, dass die kv-Sprache gebaut wird, um diese Dinge einfacher als einfache Python zu machen. Danke für den Bonus :). – Tshirtman

Verwandte Themen