Properties¶
The Properties classes are used when you create a EventDispatcher.
Warning
Kivy’s Properties are not to be confused with Python’s properties (i.e. the @property decorator and the <property> type).
Kivy’s property classes support:
- Value Checking / Validation
- When you assign a new value to a property, the value is checked to pass constraints implemented in the class such as validation. For example, validation for OptionProperty will make sure that the value is in a predefined list of possibilities. Validation for NumericProperty will check that your value is a numeric type. This prevents many errors early on.
- Observer Pattern
- You can specify what should happen when a property’s value changes. You can bind your own function as a callback to changes of a Property. If, for example, you want a piece of code to be called when a widget’s pos property changes, you can bind a function to it.
- Better Memory Management
- The same instance of a property is shared across multiple widget instances.
Comparison Python / Kivy¶
Basic example¶
Let’s compare Python and Kivy properties by creating a Python class with ‘a’ as a float:
class MyClass(object):
def __init__(self, a=1.0):
super(MyClass, self).__init__()
self.a = a
With Kivy, you can do:
class MyClass(EventDispatcher):
a = NumericProperty(1.0)
Value checking¶
If you wanted to add a check such a minimum / maximum value allowed for a property, here is a possible implementation in Python:
class MyClass(object):
def __init__(self, a=1):
super(MyClass, self).__init__()
self._a = 0
self.a_min = 0
self.a_max = 100
self.a = a
def _get_a(self):
return self._a
def _set_a(self, value):
if value < self.a_min or value > self.a_max:
raise ValueError('a out of bounds')
self._a = a
a = property(_get_a, _set_a)
The disadvantage is you have to do that work yourself. And it becomes laborious and complex if you have many properties. With Kivy, you can simplify like this:
class MyClass(EventDispatcher):
a = BoundedNumericProperty(1, min=0, max=100)
That’s all!
Error Handling¶
If setting a value would otherwise raise a ValueError, you have two options to handle the error gracefully within the property. An errorvalue is a substitute for the invalid value. An errorhandler is a callable (single argument function or lambda) which can return a valid substitute.
errorhandler parameter:
# simply returns 0 if the value exceeds the bounds
bnp = BoundedNumericProperty(0, min=-500, max=500, errorvalue=0)
errorvalue parameter:
# returns a the boundary value when exceeded
bnp = BoundedNumericProperty(0, min=-500, max=500,
errorhandler=lambda x: 500 if x > 500 else -500)
Conclusion¶
Kivy properties are easier to use than the standard ones. See the next chapter for examples of how to use them :)
Observe Properties changes¶
As we said in the beginning, Kivy’s Properties implement the Observer pattern. That means you can bind() to a property and have your own function called when the value changes.
Multiple ways are available to observe the changes.
Observe using bind()¶
You can observe a property change by using the bind() method, outside the class:
class MyClass(EventDispatcher):
a = NumericProperty(1)
def callback(instance, value):
print 'My callback is call from', instance,
print 'and the a value changed to', value
ins = MyClass()
ins.bind(a=callback)
# At this point, any change to the a property will call your callback.
ins.a = 5 # callback called
ins.a = 5 # callback not called, because the value didnt change
ins.a = -1 # callback called
Observe using ‘on_<propname>’¶
If you created the class yourself, you can use the ‘on_<propname>’ callback:
class MyClass(EventDispatcher):
a = NumericProperty(1)
def on_a(self, instance, value):
print 'My property a changed to', value
Warning
Be careful with ‘on_<propname>’. If you are creating such a callback on a property you are inherit, you must not forget to call the subclass function too.
- class kivy.properties.Property¶
Bases: object
Base class for building more complex properties.
This class handles all the basic setters and getters, None type handling, the observer list and storage initialisation. This class should not be directly instantiated.
By default, a Property always takes a default value:
class MyObject(Widget): hello = Property('Hello world')
The default value must be a value that agrees with the Property type. For example, you can’t set a list to a StringProperty, because the StringProperty will check the default value.
None is a special case: you can set the default value of a Property to None, but you can’t set None to a property afterward. If you really want to do that, you must declare the Property with allownone=True:
class MyObject(Widget): hello = ObjectProperty(None, allownone=True) # then later a = MyObject() a.hello = 'bleh' # working a.hello = None # working too, because allownone is True.
Parameters : - errorhandler: callable
If set, must take a single argument and return a valid substitute value
- errorvalue: object
If set, will replace an invalid property value (overrides errorhandler)
Changed in version 1.4.2: Parameters errorhandler and errorvalue added
- bind()¶
Add a new observer to be called only when the value is changed.
- dispatch()¶
Dispatch the value change to all observers.
Changed in version 1.1.0: The method is now accessible from Python.
This can be used to force the dispatch of the property, even if the value didn’t change:
button = Button() # get the Property class instance prop = button.property('text') # dispatch this property on the button instance prop.dispatch(button)
- get()¶
Return the value of the property.
- link()¶
Link the instance with its real name.
Warning
Internal usage only.
When a widget is defined and uses a Property class, the creation of the property object happens, but the instance doesn’t know anything about its name in the widget class:
class MyWidget(Widget): uid = NumericProperty(0)
In this example, the uid will be a NumericProperty() instance, but the property instance doesn’t know its name. That’s why link() is used in Widget.__new__. The link function is also used to create the storage space of the property for this specific widget instance.
- set()¶
Set a new value for the property.
- unbind()¶
Remove the observer from our widget observer list.
- class kivy.properties.NumericProperty¶
Bases: kivy.properties.Property
Property that represents a numeric value.
The NumericProperty accepts only int or float.
>>> wid = Widget() >>> wid.x = 42 >>> print wid.x 42 >>> wid.x = "plop" Traceback (most recent call last): File "<stdin>", line 1, in <module> File "properties.pyx", line 93, in kivy.properties.Property.__set__ File "properties.pyx", line 111, in kivy.properties.Property.set File "properties.pyx", line 159, in kivy.properties.NumericProperty.check ValueError: NumericProperty accept only int/float
Changed in version 1.4.1: NumericProperty can now accept custom text and tuple value to indicate a type, like “in”, “pt”, “px”, “cm”, “mm”, in the format: ‘10pt’ or (10, ‘pt’).
- get_format()¶
Return the format used for Numeric calculation. Default is px (mean the value have not been changed at all). Otherwise, it can be one of ‘in’, ‘pt’, ‘cm’, ‘mm’.
- class kivy.properties.StringProperty¶
Bases: kivy.properties.Property
Property that represents a string value.
Only a string or unicode is accepted.
- class kivy.properties.ListProperty¶
Bases: kivy.properties.Property
Property that represents a list.
Only lists are allowed. Tuple or any other classes are forbidden.
- class kivy.properties.ObjectProperty¶
Bases: kivy.properties.Property
Property that represents a Python object.
Warning
To mark the property as changed, you must reassign a new python object.
- class kivy.properties.BooleanProperty¶
Bases: kivy.properties.Property
Property that represents only a boolean value.
- class kivy.properties.BoundedNumericProperty¶
Bases: kivy.properties.Property
Property that represents a numeric value within a minimum bound and/or maximum bound – within a numeric range.
Parameters : - min: numeric
If set, minimum bound will be used, with the value of min
- max: numeric
If set, maximum bound will be used, with the value of max
- bounds¶
Return min/max of the value.
New in version 1.0.9.
- get_max()¶
Return the maximum value acceptable for the BoundedNumericProperty in obj. Return None if no maximum value is set. Check get_min for a usage example.
New in version 1.1.0.
- get_min()¶
Return the minimum value acceptable for the BoundedNumericProperty in obj. Return None if no minimum value is set:
class MyWidget(Widget): number = BoundedNumericProperty(0, min=-5, max=5) widget = MyWidget() print widget.property('number').get_min(widget) # will output -5
New in version 1.1.0.
- set_max()¶
Change the maximum value acceptable for the BoundedNumericProperty, only for the obj instance. Set to None if you want to disable it. Check set_min for a usage example.
Warning
Changing the bounds doesn’t revalidate the current value.
New in version 1.1.0.
- set_min()¶
Change the minimum value acceptable for the BoundedNumericProperty, only for the obj instance. Set to None if you want to disable it:
class MyWidget(Widget): number = BoundedNumericProperty(0, min=-5, max=5) widget = MyWidget() # change the minmium to -10 widget.property('number').set_min(widget, -10) # or disable the minimum check widget.property('number').set_min(widget, None)
Warning
Changing the bounds doesn’t revalidate the current value.
New in version 1.1.0.
- class kivy.properties.OptionProperty¶
Bases: kivy.properties.Property
Property that represents a string from a predefined list of valid options.
If the string set in the property is not in the list of valid options (passed at property creation time), a ValueError exception will be raised.
Parameters : - options: list (not tuple.)
List of valid options
- options¶
Return the options available.
New in version 1.0.9.
- class kivy.properties.ReferenceListProperty¶
Bases: kivy.properties.Property
Property that allows the creaton of a tuple of other properties.
For example, if x and y are NumericProperty`s, we can create a :class:`ReferenceListProperty for the pos. If you change the value of pos, it will automatically change the values of x and y accordingly. If you read the value of pos, it will return a tuple with the values of x and y.
- class kivy.properties.AliasProperty¶
Bases: kivy.properties.Property
Create a property with a custom getter and setter.
If you don’t find a Property class that fits to your needs, you can make your own by creating custom Python getter and setter methods.
Example from kivy/uix/widget.py:
def get_right(self): return self.x + self.width def set_right(self, value): self.x = value - self.width right = AliasProperty(get_right, set_right, bind=('x', 'width'))
Parameters : - getter: function
Function to use as a property getter
- setter: function
Function to use as a property setter
- bind: list/tuple
Properties to observe for changes, as property name strings
- cache: boolean
If True, the value will be cached, until one of the binded elements will changes
Changed in version 1.4.0: Parameter cache added.
- class kivy.properties.DictProperty¶
Bases: kivy.properties.Property
Property that represents a dict.
Only dict are allowed. Any other classes are forbidden.