mirror of https://github.com/kivy/kivy.git
Small corrections and improvements to the docs, 'guide2/events.rst'.
This commit is contained in:
parent
0aca105887
commit
71e98b6f20
|
@ -4,32 +4,31 @@
|
|||
Events and Properties
|
||||
=====================
|
||||
|
||||
Events are a big part of kivy programming, that may not be surprising to those
|
||||
having done GUI development before, but it's an important concept to get for
|
||||
newcomers, and the specifics of how to use these in kivy. Once you understand
|
||||
how events and ways to bind to them, are everywhere in kivy, it becomes easy to
|
||||
build about whatever you want with kivy.
|
||||
Events are an important part of kivy programming. That may not be surprising to those
|
||||
with GUI development experience, but it's an important concept for
|
||||
newcomers. Once you understand how events work and how to bind to them,
|
||||
you will see them everywhere in kivy. They make it easy to
|
||||
build whatever behaviour you want into kivy.
|
||||
|
||||
The following illustration tries to represent the relationship between the
|
||||
events and the rest of kivy.
|
||||
The following illustration shows how events are handled in the kivy framework.
|
||||
|
||||
.. image:: images/Events.*
|
||||
|
||||
Introduction to Event Dispatcher
|
||||
--------------------------------
|
||||
Introduction to the Event Dispatcher
|
||||
------------------------------------
|
||||
|
||||
One of the most important base classes of the framework is the
|
||||
:class:`~kivy.event.EventDispatcher` class, this class allows to register event
|
||||
types, and to dispatch them to interested parties (usually other event
|
||||
dispatchers). :class:`~kivy.uix.widget.Widget`,
|
||||
:class:`~kivy.animation.Animation` and :obj:`~kivy.clock.Clock` for example are
|
||||
event dispatchers.
|
||||
:class:`~kivy.event.EventDispatcher` class. This class allows you to register
|
||||
event types, and to dispatch them to interested parties (usually other event
|
||||
dispatchers). The :class:`~kivy.uix.widget.Widget`,
|
||||
:class:`~kivy.animation.Animation` and :obj:`~kivy.clock.Clock` classes are
|
||||
examples of event dispatchers.
|
||||
|
||||
Creating custom events
|
||||
----------------------
|
||||
|
||||
To create an event dispatcher with custom events, you need to register the name
|
||||
of the event in the class, and to create a method of the same name.
|
||||
of the event in the class and then create a method of the same name.
|
||||
|
||||
See the following example::
|
||||
|
||||
|
@ -50,13 +49,13 @@ See the following example::
|
|||
Attaching callbacks
|
||||
-------------------
|
||||
|
||||
To use events, you have to bind callbacks to them, when the event is
|
||||
dispatched, your callbacks will be called with the various data the event has
|
||||
to pass around.
|
||||
To use events, you have to bind callbacks to them. When the event is
|
||||
dispatched, your callbacks will be called with the parameters relevant to
|
||||
that specific event.
|
||||
|
||||
A callback can be any python callable, but you need to be sure it can accept
|
||||
the arguments the event will use, for this, it's usually safer to accept the
|
||||
`*args` argument, that will catch any remaining arguments in the `args` list.
|
||||
A callback can be any python callable, but you need to ensure it accepts
|
||||
the arguments that the event emits. For this, it's usually safest to accept the
|
||||
`*args` argument, which will catch all arguments in the `args` list.
|
||||
|
||||
Example::
|
||||
|
||||
|
@ -72,12 +71,12 @@ Example::
|
|||
Introduction to properties
|
||||
--------------------------
|
||||
|
||||
Properties are an awesome way to define events and bind to them, it basically
|
||||
produce events when the attributes of your object changes, so you can bind
|
||||
actions to the change of these values.
|
||||
Properties are an awesome way to define events and bind to them. Essentially,
|
||||
they produce events such that when an attribute of your object changes,
|
||||
all properties that reference that attribute are automatically updated.
|
||||
|
||||
There are different kind of properties to describe the type of data you want to
|
||||
describe.
|
||||
There are different kinds of properties to describe the type of data you want to
|
||||
handle.
|
||||
|
||||
- :class:`~kivy.properties.StringProperty`
|
||||
- :class:`~kivy.properties.NumericProperty`
|
||||
|
@ -94,9 +93,9 @@ describe.
|
|||
Declaration of a Property
|
||||
-------------------------
|
||||
|
||||
To declare a property, you must create it at class level, the class will do the
|
||||
work to instantiate the real attributes when the object will be created, the
|
||||
properties is not the attribute, it's a mechanism to create events for your
|
||||
To declare properties, you must declare them at the class level. The class will then do
|
||||
the work to instantiate the real attributes when your object is created. These properties
|
||||
are not attributes: they are mechanisms for creating events based on your
|
||||
attributes::
|
||||
|
||||
class MyWidget(Widget):
|
||||
|
@ -104,8 +103,8 @@ attributes::
|
|||
text = StringProperty('')
|
||||
|
||||
|
||||
When overriding `__init__`, *always* accept `**kwargs` and use super() to call
|
||||
the parents `__init__` with it::
|
||||
When overriding `__init__`, *always* accept `**kwargs` and use `super()` to call
|
||||
the parents `__init__` method, passing in your class instance::
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(MyWidget, self).__init__(**kwargs)
|
||||
|
@ -114,14 +113,14 @@ the parents `__init__` with it::
|
|||
Dispatching a Property event
|
||||
----------------------------
|
||||
|
||||
Kivy properties by default provide a on_<property_name> event. This event is
|
||||
Kivy properties, by default, provide an `on_<property_name>` event. This event is
|
||||
called when the value of the property is changed.
|
||||
|
||||
.. note::
|
||||
if the new value for the property is equal to the older value then the
|
||||
on_<property_name> event will not be called.
|
||||
If the new value for the property is equal to the current value, then the
|
||||
`on_<property_name>` event will not be called.
|
||||
|
||||
For example consider the following code.
|
||||
For example, consider the following code:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
@ -139,13 +138,13 @@ For example consider the following code.
|
|||
def on_pressed(self, instance, pos):
|
||||
print ('pressed at {pos}'.format(pos=pos))
|
||||
|
||||
In the code above at line: 3 ::
|
||||
In the code above at line 3::
|
||||
|
||||
pressed = ListProperty([0, 0])
|
||||
|
||||
We define `pressed` Property of type :class:`~kivy.properties.ListProperty`,
|
||||
giving it a default value of `[0, 0]`. from this point on-wards the `on_pressed`
|
||||
event will be called when ever the value of this property is changed.
|
||||
We define the `pressed` Property of type :class:`~kivy.properties.ListProperty`,
|
||||
giving it a default value of `[0, 0]`. From this point onwards, the `on_pressed`
|
||||
event will be called whenever the value of this property is changed.
|
||||
|
||||
At Line 5::
|
||||
|
||||
|
@ -155,39 +154,39 @@ At Line 5::
|
|||
return True
|
||||
return super(CustomBtn, self).on_touch_down(touch)
|
||||
|
||||
We override the :meth:`on_touch_down` method of the Widget class. Here we check
|
||||
We override the :meth:`on_touch_down` method of the Widget class. Here, we check
|
||||
for collision of the `touch` with our widget.
|
||||
|
||||
If it falls inside our widget, we change the value of `pressed` to touch.pos
|
||||
and return True indicating that we have consumed the touch and don't want it
|
||||
propagating any further.
|
||||
If the touch falls inside of our widget, we change the value of `pressed` to touch.pos
|
||||
and return True, indicating that we have consumed the touch and don't want it
|
||||
propagate any further.
|
||||
|
||||
Then finally if the touch falls outside our widget, we call the original event
|
||||
using super(...)... and return the result so as to allow propagation of touch
|
||||
to continue as it would otherwise have.
|
||||
Finally, if the touch falls outside our widget, we call the original event
|
||||
using `super(...)` and return the result. This allows the touch event propagation
|
||||
to continue as it would normally have occured.
|
||||
|
||||
Finally on line 11::
|
||||
|
||||
def on_pressed(self, instance, pos):
|
||||
print ('pressed at {pos}'.format(pos=pos))
|
||||
|
||||
We define `on_pressed` function that will be called by the property whenever the
|
||||
We define an `on_pressed` function that will be called by the property whenever the
|
||||
property value is changed.
|
||||
|
||||
.. Note::
|
||||
This `on_<prop_name>` event is called within the class that the property is
|
||||
defined in. To monitor/observe the change to a property outside of a class
|
||||
it's defined in you should bind to the property.
|
||||
it's defined in, you should bind to the property.
|
||||
|
||||
|
||||
**Binding to the property**
|
||||
|
||||
How to monitor changes to a property when all you have access to is a widget's
|
||||
instance? You Bind to the property::
|
||||
instance? You *bind* to the property::
|
||||
|
||||
your_widget_instance.bind(property_name=function_name)
|
||||
|
||||
For example consider the following code.
|
||||
For example, consider the following code:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
@ -205,7 +204,7 @@ For example consider the following code.
|
|||
def btn_pressed(self, instance, pos):
|
||||
print ('pos: printed from root widget: {pos}'.format(pos=.pos))
|
||||
|
||||
If you run the code as is you will notice two print statements in the console.
|
||||
If you run the code as is, you will notice two print statements in the console.
|
||||
One from the `on_pressed` event that is called inside the `CustomBtn` class and
|
||||
one from the `btn_pressed` function that we bind to the property change.
|
||||
|
||||
|
@ -213,15 +212,15 @@ The reason that both the functions are called is simple. Binding doesn't mean
|
|||
overriding. Having both of these functions is redundant and you should generally
|
||||
only use one of the methods of listening/reacting to property changes.
|
||||
|
||||
You should also take note about the parameters that are passed to the
|
||||
on_<property_name> event or the function bound to the property.
|
||||
You should also take note of the parameters that are passed to the
|
||||
`on_<property_name>` event or the function bound to the property.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def btn_pressed(self, instance, pos):
|
||||
|
||||
The first parameter is self which is the instance of the class this function is
|
||||
defined in. If you use a in-line function like so.
|
||||
The first parameter is `self`, which is the instance of the class this function is
|
||||
defined in. You can use an in-line function as follows:
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
@ -234,13 +233,13 @@ defined in. If you use a in-line function like so.
|
|||
cb.bind(pressed=_local_func)
|
||||
self.add_widget(cb)
|
||||
|
||||
Then the first parameter would be `instance` of the class the property is
|
||||
The first parameter would be `instance` of the class the property is
|
||||
defined in.
|
||||
|
||||
The last parameter is the `value` which is the new value of the property.
|
||||
The second parameter would be the `value`, which is the new value of the property.
|
||||
|
||||
This is the complete runnable code derived from the snippets above that you can
|
||||
use to copy and paste into a editor to experiment with.
|
||||
Here is the complete example, derived from the snippets above, that you can
|
||||
use to copy and paste into an editor to experiment with.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
@ -289,18 +288,19 @@ use to copy and paste into a editor to experiment with.
|
|||
TestApp().run()
|
||||
|
||||
|
||||
Running the code above will give you the following output.
|
||||
|
||||
Our CustomBtn has no visual representation and thus appears black. You can
|
||||
touch/click on the black area to see the output on your console
|
||||
Running the code above will give you the following output:
|
||||
|
||||
.. image:: images/property_events_binding.png
|
||||
|
||||
Some Gotchas in AliasProperty and ReferenceListProperty.
|
||||
Our CustomBtn has no visual representation and thus appears black. You can
|
||||
touch/click on the black area to see the output on your console.
|
||||
|
||||
While defining a AliasProperty you normally define a getter and a setter
|
||||
function yourself. Here It falls on to you to define when the getter and the
|
||||
setter functions are called using the `bind` argument.
|
||||
Some Gotchas in :class:`~kivy.properties.AliasProperty` and
|
||||
:class:`~kivy.properties.ReferenceListProperty`.
|
||||
|
||||
When defining an :class:`~kivy.properties.AliasProperty`, you normally define
|
||||
a getter and a setter functions yourself. Here, it falls on to you to define
|
||||
when the getter and the setter functions are called using the `bind` argument.
|
||||
|
||||
Consider the following code.
|
||||
|
||||
|
|
Loading…
Reference in New Issue