Table Of Contents
Kivy Namespaces¶
New in version 1.9.1.
Warning
This code is still experimental, and its API is subject to change in a future version.
The KNSpaceBehavior
mixin
class provides namespace functionality for Kivy objects. It allows kivy objects
to be named and then accessed using namespaces.
KNSpace
instances are the namespaces that store the named objects
in Kivy ObjectProperty
instances.
In addition, when inheriting from KNSpaceBehavior
, if the derived
object is named, the name will automatically be added to the associated
namespace and will point to a proxy_ref
of the
derived object.
Basic examples¶
By default, there’s only a single namespace: the knspace
namespace. The
simplest example is adding a widget to the namespace:
from kivy.uix.behaviors.knspace import knspace
widget = Widget()
knspace.my_widget = widget
This adds a kivy ObjectProperty
with rebind=True
and allownone=True to the knspace
namespace with a property name
my_widget. And the property now also points to this widget.
This can be done automatically with:
class MyWidget(KNSpaceBehavior, Widget):
pass
widget = MyWidget(knsname='my_widget')
Or in kv:
<MyWidget@KNSpaceBehavior+Widget>
MyWidget:
knsname: 'my_widget'
Now, knspace.my_widget will point to that widget.
When one creates a second widget with the same name, the namespace will also change to point to the new widget. E.g.:
widget = MyWidget(knsname='my_widget')
# knspace.my_widget now points to widget
widget2 = MyWidget(knsname='my_widget')
# knspace.my_widget now points to widget2
Setting the namespace¶
One can also create ones own namespace rather than using the default
knspace
by directly setting KNSpaceBehavior.knspace
:
class MyWidget(KNSpaceBehavior, Widget):
pass
widget = MyWidget(knsname='my_widget')
my_new_namespace = KNSpace()
widget.knspace = my_new_namespace
Initially, my_widget is added to the default namespace, but when the widget’s namespace is changed to my_new_namespace, the reference to my_widget is moved to that namespace. We could have also of course first set the namespace to my_new_namespace and then have named the widget my_widget, thereby avoiding the initial assignment to the default namespace.
Similarly, in kv:
<MyWidget@KNSpaceBehavior+Widget>
MyWidget:
knspace: KNSpace()
knsname: 'my_widget'
Inheriting the namespace¶
In the previous example, we directly set the namespace we wished to use. In the following example, we inherit it from the parent, so we only have to set it once:
<MyWidget@KNSpaceBehavior+Widget>
<MyLabel@KNSpaceBehavior+Label>
<MyComplexWidget@MyWidget>:
knsname: 'my_complex'
MyLabel:
knsname: 'label1'
MyLabel:
knsname: 'label2'
Then, we do:
widget = MyComplexWidget()
new_knspace = KNSpace()
widget.knspace = new_knspace
The rule is that if no knspace has been assigned to a widget, it looks for a
namespace in its parent and parent’s parent and so on until it find one to
use. If none are found, it uses the default knspace
.
When MyComplexWidget is created, it still used the default namespace. However, when we assigned the root widget its new namespace, all its children switched to using that new namespace as well. So new_knspace now contains label1 and label2 as well as my_complex.
If we had first done:
widget = MyComplexWidget()
new_knspace = KNSpace()
knspace.label1.knspace = knspace
widget.knspace = new_knspace
Then label1 would remain stored in the default knspace
since it was
directly set, but label2 and my_complex would still be added to the new
namespace.
One can customize the attribute used to search the parent tree by changing
KNSpaceBehavior.knspace_key
. If the desired knspace is not reachable
through a widgets parent tree, e.g. in a popup that is not a widget’s child,
KNSpaceBehavior.knspace_key
can be used to establish a different
search order.
Accessing the namespace¶
As seen in the previous example, if not directly assigned, the namespace is
found by searching the parent tree. Consequently, if a namespace was assigned
further up the parent tree, all its children and below could access that
namespace through their KNSpaceBehavior.knspace
property.
This allows the creation of multiple widgets with identically given names if each root widget instance is assigned a new namespace. For example:
<MyComplexWidget@KNSpaceBehavior+Widget>:
Label:
text: root.knspace.pretty.text if root.knspace.pretty else ''
<MyPrettyWidget@KNSpaceBehavior+TextInput>:
knsname: 'pretty'
text: 'Hello'
<MyCompositeWidget@KNSpaceBehavior+BoxLayout>:
MyComplexWidget
MyPrettyWidget
Now, when we do:
knspace1, knspace2 = KNSpace(), KNSpace()
composite1 = MyCompositeWidget()
composite1.knspace = knspace1
composite2 = MyCompositeWidget()
composite2.knspace = knspace2
knspace1.pretty = "Here's the ladder, now fix the roof!"
knspace2.pretty = "Get that raccoon off me!"
Because each of the MyCompositeWidget instances have a different namespace their children also use different namespaces. Consequently, the pretty and complex widgets of each instance will have different text.
Further, because both the namespace ObjectProperty
references, and KNSpaceBehavior.knspace
have rebind=True, the
text of the MyComplexWidget label is rebound to match the text of
MyPrettyWidget when either the root’s namespace changes or when the
root.knspace.pretty property changes, as expected.
Forking a namespace¶
Forking a namespace provides the opportunity to create a new namespace from a parent namespace so that the forked namespace will contain everything in the origin namespace, but the origin namespace will not have access to anything added to the forked namespace.
For example:
child = knspace.fork()
grandchild = child.fork()
child.label = Label()
grandchild.button = Button()
Now label is accessible by both child and grandchild, but not by knspace. And button is only accessible by the grandchild but not by the child or by knspace. Finally, doing grandchild.label = Label() will leave grandchild.label and child.label pointing to different labels.
A motivating example is the example from above:
<MyComplexWidget@KNSpaceBehavior+Widget>:
Label:
text: root.knspace.pretty.text if root.knspace.pretty else ''
<MyPrettyWidget@KNSpaceBehavior+TextInput>:
knsname: 'pretty'
text: 'Hello'
<MyCompositeWidget@KNSpaceBehavior+BoxLayout>:
knspace: 'fork'
MyComplexWidget
MyPrettyWidget
Notice the addition of knspace: ‘fork’. This is identical to doing
knspace: self.knspace.fork(). However, doing that would lead to infinite
recursion as that kv rule would be executed recursively because self.knspace
will keep on changing. However, allowing knspace: ‘fork’ cirumvents that.
See KNSpaceBehavior.knspace
.
Now, having forked, we just need to do:
composite1 = MyCompositeWidget()
composite2 = MyCompositeWidget()
composite1.knspace.pretty = "Here's the ladder, now fix the roof!"
composite2.knspace.pretty = "Get that raccoon off me!"
Since by forking we automatically created a unique namespace for each MyCompositeWidget instance.
- class kivy.uix.behaviors.knspace.KNSpace(parent=None, keep_ref=False, **kwargs)[source]¶
Bases:
kivy.event.EventDispatcher
Each
KNSpace
instance is a namespace that stores the named Kivy objects associated with this namespace. Each named object is stored as the value of a KivyObjectProperty
of this instance whose property name is the object’s given name. Both rebind and allownone are set to True for the property.See
KNSpaceBehavior.knspace
for details on how a namespace is associated with a named object.When storing an object in the namespace, the object’s proxy_ref is stored if the object has such an attribute.
- Parameters
- fork()[source]¶
Returns a new
KNSpace
instance which will have access to all the named objects in the current namespace but will also have a namespace of its own that is unique to it.For example:
forked_knspace1 = knspace.fork() forked_knspace2 = knspace.fork()
Now, any names added to knspace will be accessible by the forked_knspace1 and forked_knspace2 namespaces by the normal means. However, any names added to forked_knspace1 will not be accessible from knspace or forked_knspace2. Similar for forked_knspace2.
- keep_ref = False¶
Whether a direct reference should be kept to the stored objects. If
True
, we use the direct object, otherwise we useproxy_ref
when present.Defaults to False.
- property(self, name, quiet=False)[source]¶
Get a property instance from the property name. If quiet is True, None is returned instead of raising an exception when name is not a property. Defaults to False.
New in version 1.0.9.
- Returns
A
Property
derived instance corresponding to the name.
Changed in version 1.9.0: quiet was added.
- class kivy.uix.behaviors.knspace.KNSpaceBehavior(knspace=None, **kwargs)[source]¶
Bases:
builtins.object
Inheriting from this class allows naming of the inherited objects, which are then added to the associated namespace
knspace
and accessible through it.Please see the
knspace behaviors module
documentation for more information.- knsname¶
The name given to this instance. If named, the name will be added to the associated
knspace
namespace, which will then point to the proxy_ref of this instance.When named, one can access this object by e.g. self.knspace.name, where name is the given name of this instance. See
knspace
and the module description for more details.
- knspace¶
The namespace instance,
KNSpace
, associated with this widget. Theknspace
namespace stores this widget when naming this widget withknsname
.If the namespace has been set with a
KNSpace
instance, e.g. with self.knspace = KNSpace(), then that instance is returned (setting with None doesn’t count). Otherwise, ifknspace_key
is not None, we look for a namespace to use in the object that is stored in the property namedknspace_key
, of this instance. I.e. object = getattr(self, self.knspace_key).If that object has a knspace property, then we return its value. Otherwise, we go further up, e.g. with getattr(object, self.knspace_key) and look for its knspace property.
Finally, if we reach a value of None, or
knspace_key
was None, the defaultknspace
namespace is returned.If
knspace
is set to the string ‘fork’, the current namespace inknspace
will be forked withKNSpace.fork()
and the resulting namespace will be assigned to this instance’sknspace
. See the module examples for a motivating example.Both rebind and allownone are True.
- kivy.uix.behaviors.knspace.knspace = <kivy.uix.behaviors.knspace.KNSpace object>¶
The default
KNSpace
namespace. SeeKNSpaceBehavior.knspace
for more details.