Data driven variables with kivy properties
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!
In our Kivy game, we have a cat object.
#!Python 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 catFactory.py
#!Python class CatFactory(): def GenerateCats(inRootWidget): cat1 = Cat() cat1.mCatSpeed = 10 cat1.mCatMass = 100 inRootWidget.add_widget(cat1) 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:
#!text <Room>: Cat: id: fatCat pos: 100, 100 mCatSpeed: 10 mCatMass: 100 Cat: 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!
For a variable to be settable, like this by kivy, it must be a kivy property.
#!python 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!
#!python 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)
This sample is very basic, and shows how you can get the above results.
#!python from kivy.app import App from kivy.lang import Builder from kivy.uix.widget import Widget from kivy.properties import StringProperty, NumericProperty, ObjectProperty # This import is required for the TestWidet.kv file to know what a Cat is. import cat Builder.load_file("TestWidget.kv") class TapApp(App): def build(self): return TestWidget() class TestWidget(Widget): pass if __name__ in ('__main__', '__android__'): TapApp().run()
#!text <TestWidget>: Cat: pos: 100, 100 catSpeed: 30
#!python from kivy.lang import Builder from kivy.uix.widget import Widget from kivy.properties import StringProperty, NumericProperty, ObjectProperty from kivy.clock import Clock Builder.load_file("Cat.kv") 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): print(self.catSpeed)