WebOrCode
WebOrCode

Reputation: 7294

How to start animation when property is updated in kivy?

This is my code:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import NumericProperty


Builder.load_string('''
<Simple>:
    Label:
        text: str( root.sometext )
    Button:
        text: '+++'
        on_release: root.inc()
''')


class Simple(BoxLayout):
    sometext = NumericProperty(0)

    def __init__(self, **kwargs):
        super(Simple, self).__init__(**kwargs)

        self.sometext = 5

    def inc(self):
        self.sometext += 5 


class TApp(App):
    def build(self):
        return Simple()


TApp().run()

Everything is working, every time when button is presses label is updated by 5.

What I wont to add is some animation. Like: before update number goes to left, and when updated number comes from right. If this is animation complicated, others concept are welcomed.

How can it be done ? I looked documentation but every example is with postion, not with text update (or at least what I have found).

Upvotes: 2

Views: 2240

Answers (2)

toto_tico
toto_tico

Reputation: 19027

@inclement is right. I don't think it is possible to animate the text directly, however it is possible to animate the Label. It is also possible to concatenate animations (operator '+') and use the event on_complete of the animation to put things in the middle like the incrementation you are looking for.

It is simple but you need a few changes in the code:

  1. You need to be able to access the Label from Python:

    1.1. Add an id to the label:

    Label:
        id: _the_label
    

    1.2. Add an ObjectProperty to the Simple class:

    class Simple(BoxLayout):
        the_label = ObjectProperty(None)
    

    1.3. "Connect" the id and the ObjectProperty:

    <Simple>:
       the_label: _the_label
    
  2. Make sure the Label has space to move to left or right. One way of do it:

    2.1 Embed the Label into another Widget, in this case RelativeLayout:

    RelativeLayout:
       Label:
    

    2.2 Define a size for the Label and center it:

    size_hint: 0.3, 0.1
    center_x: self.parent.width/2
    center_y: self.parent.height/2
    
  3. Now you can proceed to create the method that animates the Label:

    def animate(self):
        left = Animation(x=0, color= [0,0,0,0])
        left.bind(on_complete=self.inc)
        right = Animation(center_x=self.the_label.parent.width/2, color= [1,1,1,1])
        anim = left + right
        anim.start(self.the_label)
    
    def inc(self, instance, value):
        self.sometext += 5 
    

    Notice: The bind to the left animation of the on_complete to the method inc. Also notice anim = left + right to concatenate the two animations. There is also the operator * to run parallel animations.

Even though it is not possible to animate the text directly, some of the properties of the Label affects it indirectly. For example, font_size, color, etc. Here is a complete list. I am positive that there should be a way to hack the moving of the text through the animation of the padding property, if you really need to animate the text.

The final code is here:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import NumericProperty, ObjectProperty
from kivy.animation import Animation

Builder.load_string('''
<Simple>:
    the_label: _the_label
    RelativeLayout:
        Label:
            id: _the_label
            size_hint: 0.3, 0.1
            center_x: self.parent.width/2
            center_y: self.parent.height/2
            text: str( root.sometext )
    Button:
        text: '+++'
        on_release: root.animate()
''')


class Simple(BoxLayout):
    the_label = ObjectProperty(None)
    sometext = NumericProperty(5)

    def animate(self):
        left = Animation(x=0)
        left.bind(on_complete=self.inc)
        right = Animation(center_x=self.the_label.parent.width/2)
        anim = left + right
        anim.start(self.the_label)

    def inc(self, instance, value):
        self.sometext += 5 

class TApp(App):
    def build(self):
        return Simple()

TApp().run()

Upvotes: 4

inclement
inclement

Reputation: 29458

How can it be done ? I looked documentation but every example is with postion, not with text update (or at least what I have found).

Kivy's animations modify specific properties, and I don't think animating text actually makes sense in this context.

It sounds like to get the behaviour you want you'll really need to add one or more labels whose positions are animated to get the movement effect - that is, the Animation class doesn't let you animate one property (text) by changing others (pos), it only relates to changing one specific property in one specific way.

If this is animation complicated, others concept are welcomed.

If I wanted to do this, I'd actually look at using a Carousel widget with two labels. The inc method would change the text of the currently hidden label, then call the Carousel method that switches the currently visible widget. The Carousel already has an animation where the first widget slides off while the next slides on, so it would take care of the details for you.

This is pretty specific though, using Carousel just happens to work well for your particular problem. I think the real answer to your question is the fact that you need to think about adding more complex behaviour on your own, because it isn't a case of just animating one property.

Upvotes: 1

Related Questions