Data driven variables with kivy properties

Mathieu Virbel edited this page Sep 27, 2013 · 1 revision
Clone this wiki locally


When working in big apps, it can be useful to expose your widgets, and variables. This allows you to easily change the data for any of the widgets through a .kv file. Also, it allows non-programmers to make signifigant changes to the application, without having to dive into code!

The Problem

In our Kivy game, we have a cat object.

class Cat(Widget):
    mCatSpeed = NumericProperty(20)
    mCatMass = NumericProperty(50)

    def Update(self, dt):
        # Do physics calculations based on Speed and Mass

As you can see here, our python "cat" object is a Kivy Widget that has a few custom member variables: mCatSpeed and mCatMass.

What happens when you want to have 2 different cats, of different speeds? The larger cats go slower, the lighter cats go faster.

You could write code to generate these objects

class CatFactory():
    def GenerateCats(inRootWidget):
        cat1 = Cat()
        cat1.mCatSpeed = 10
        cat1.mCatMass = 100

        cat2 = cat()
        # ...etc

But now every time you want to change the cats, you have to go into this code and change the varaibles, and copy a lot of code with different names.

What happens when you want cats in different areas? Things start to get messy.

Data Driven Solution

Kivy allows us to data drive our application, which is a super useful, super powerful solution.

Lets say our cat lives inside a room, lets make the 3 cats like this:


        id: fatCat
        pos: 100, 100
        mCatSpeed: 10
        mCatMass: 100

        id: smallCat
        pos: 100, 50
        mCatSpeed: 50
        mCatMass: 25

Pretty handy, right? You can now just write your different cats with whatever data you want, assuming they are set up the way you need.

What's better is that non-programmers (Artists, Designers) can now create large portions of your applications much more rapidly than doing it through code!

The technical

For a variable to be settable, like this by kivy, it must be a kivy property.

class MyWidget(Widget):
    # Can be set in .kv files, since its a Kivy Property
    speed1 = NumericProperty(0)
    # Cannot be set, its not a Kivy Property
    speed2 = 0

The variable is a bit finicky with naming too. It must be lowercased first letter!

class MyWidget(Widget):
    # Works, as the first character is lowercased
    speed1 = NumericProperty(0)
    sPEEd2 = NumericProperty(0)
    # Does not work, as the first character is capitalized
    Speed3 = NumericProperty(0)

Sample Code

This sample is very basic, and shows how you can get the above results.

from import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from import StringProperty, NumericProperty, ObjectProperty
# This import is required for the TestWidet.kv file to know what a Cat is.
import cat


class TapApp(App):
    def build(self):
        return TestWidget()

class TestWidget(Widget):

if __name__ in ('__main__', '__android__'):


        pos: 100, 100
        catSpeed: 30

from kivy.lang import Builder
from kivy.uix.widget import Widget
from import StringProperty, NumericProperty, ObjectProperty
from kivy.clock import Clock


class Cat(Widget):
    catSpeed = NumericProperty(20)

    def __init__(self, **kwargs):
        super(Cat, self).__init__(**kwargs)
        Clock.schedule_interval(self.Update, 1.0 / 60.0)

    def Update(self, dt):