目录
Kivy 命名空间¶
在 1.9.1 版本加入.
警告
此代码仍处于实验阶段,其API在未来的版本中可能会有所变动。
:类 KNSpaceBehavior 是一个 mixin 类,为 Kivy 对象提供命名空间功能。它允许 Kivy 对象被命名,并通过命名空间进行访问。
KNSpace 实例是存储 Kivy ObjectProperty 实例中命名对象的命名空间。此外,当从 KNSpaceBehavior 继承时,如果派生对象被命名,该名称将自动添加到关联的命名空间中,并指向派生对象的 proxy_ref。
基本示例¶
默认情况下,只有一个命名空间:即 knspace 命名空间。最简单的示例是向该命名空间添加一个部件:
from kivy.uix.behaviors.knspace import knspace
widget = Widget()
knspace.my_widget = widget
这会在 knspace 命名空间中添加一个带有 rebind=True 和 allownone=True 的 kivy ObjectProperty,属性名为 my_widget。并且该属性现在也指向此控件。
可以使用以下方式自动完成:
class MyWidget(KNSpaceBehavior, Widget):
pass
widget = MyWidget(knsname='my_widget')
或者在kv中:
<MyWidget@KNSpaceBehavior+Widget>
MyWidget:
knsname: 'my_widget'
现在,knspace.my_widget 将指向该控件。
当创建另一个同名的新控件时,命名空间也会更新以指向这个新控件。例如:
widget = MyWidget(knsname='my_widget')
# knspace.my_widget now points to widget
widget2 = MyWidget(knsname='my_widget')
# knspace.my_widget now points to widget2
设置命名空间¶
也可以通过直接设置 KNSpaceBehavior.knspace 来创建自己的命名空间,而不是使用默认的 knspace。
class MyWidget(KNSpaceBehavior, Widget):
pass
widget = MyWidget(knsname='my_widget')
my_new_namespace = KNSpace()
widget.knspace = my_new_namespace
最初,my_widget 被添加到默认命名空间中,但当小部件的命名空间更改为 my_new_namespace 时,对 my_widget 的引用会移动到该命名空间。当然,我们也可以先将命名空间设置为 my_new_namespace,然后再将小部件命名为 my_widget,从而避免初始分配到默认命名空间。
同样地,在kv中:
<MyWidget@KNSpaceBehavior+Widget>
MyWidget:
knspace: KNSpace()
knsname: 'my_widget'
继承命名空间¶
在之前的例子中,我们直接设置了想要使用的命名空间。在下面的例子中,我们从父级继承它,因此只需设置一次:
<MyWidget@KNSpaceBehavior+Widget>
<MyLabel@KNSpaceBehavior+Label>
<MyComplexWidget@MyWidget>:
knsname: 'my_complex'
MyLabel:
knsname: 'label1'
MyLabel:
knsname: 'label2'
然后,我们执行以下操作:
widget = MyComplexWidget()
new_knspace = KNSpace()
widget.knspace = new_knspace
规则是:如果某个控件没有被分配 knspace,它会依次在其父控件、父控件的父控件等层级中查找命名空间,直到找到一个可用的为止。如果都没有找到,则使用默认的 knspace。
当创建 MyComplexWidget 时,它仍然使用默认的命名空间。然而,当我们为根部件分配了新的命名空间后,其所有子部件也都切换到了使用该新命名空间。因此,new_knspace 现在包含了 label1、label2 以及 my_complex。
如果我们首先完成了:
widget = MyComplexWidget()
new_knspace = KNSpace()
knspace.label1.knspace = knspace
widget.knspace = new_knspace
那么,label1 由于是直接设置的,仍会保留在默认的 knspace 中,而 label2 和 my_complex 则会被添加到新的命名空间中。
可以通过修改 KNSpaceBehavior.knspace_key 属性来自定义用于搜索父级树的属性。如果所需的 knspace 无法通过小部件的父级树访问,例如在不是小部件子级的弹出窗口中,可以使用 KNSpaceBehavior.knspace_key 来建立不同的搜索顺序。
访问命名空间¶
如前面的例子所示,如果未直接赋值,命名空间会通过搜索父级树来找到。因此,如果在父级树更上层分配了命名空间,其所有子级及以下层级都能通过它们的 KNSpaceBehavior.knspace 属性访问该命名空间。
这允许在给每个根部件实例分配新的命名空间时,创建多个具有相同名称的部件。例如:
<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
现在,当我们执行:
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!"
由于每个 MyCompositeWidget 实例都有不同的命名空间,它们的子部件也使用不同的命名空间。因此,每个实例的 pretty 和 complex 部件将具有不同的文本。
此外,由于命名空间 ObjectProperty 引用和 KNSpaceBehavior.knspace 都设置了 rebind=True,因此当根命名空间发生变化或 root.knspace.pretty 属性改变时,MyComplexWidget 标签的文本会按预期重新绑定,以匹配 MyPrettyWidget 的文本。
分叉命名空间¶
分叉命名空间提供了从父命名空间创建新命名空间的机会,这样分叉后的命名空间将包含原始命名空间中的所有内容,但原始命名空间将无法访问添加到分叉命名空间中的任何内容。
例如:
child = knspace.fork()
grandchild = child.fork()
child.label = Label()
grandchild.button = Button()
现在,标签(label)既可以通过子组件(child)访问,也可以通过孙组件(grandchild)访问,但不能通过 knspace 访问。而按钮(button)只能通过孙组件访问,不能通过子组件或 knspace 访问。最后,执行 grandchild.label = Label() 会使 grandchild.label 和 child.label 指向不同的标签对象。
一个激励性的例子就是上面提到的那个例子:
<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
注意添加了 knspace: 'fork'。这等同于执行 knspace: self.knspace.fork()。然而,这样做会导致无限递归,因为该 kv 规则会被递归执行,因为 self.knspace 会不断变化。但是,允许 knspace: 'fork' 可以规避这个问题。参见 KNSpaceBehavior.knspace。
现在,既然已经完成了分叉,我们只需要执行:
composite1 = MyCompositeWidget()
composite2 = MyCompositeWidget()
composite1.knspace.pretty = "Here's the ladder, now fix the roof!"
composite2.knspace.pretty = "Get that raccoon off me!"
由于通过分叉,我们自动为每个`MyCompositeWidget`实例创建了唯一的命名空间。
- class kivy.uix.behaviors.knspace.KNSpace(parent=None, keep_ref=False, **kwargs)[源代码]¶
-
每个
KNSpace实例都是一个命名空间,用于存储与该命名空间关联的命名 Kivy 对象。每个命名对象都作为该实例的一个 KivyObjectProperty属性的值存储,该属性的名称即为对象的给定名称。对于该属性,rebind 和 allownone 均设置为 True。关于命名空间如何与命名对象关联的详细信息,请参阅
KNSpaceBehavior.knspace。在命名空间中存储对象时,如果该对象具有 proxy_ref 属性,则存储的是该对象的 proxy_ref。
- 参数:
- fork()[源代码]¶
返回一个新的
KNSpace实例,该实例将能够访问当前命名空间中的所有命名对象,同时也会拥有一个独立且唯一的命名空间。例如:
forked_knspace1 = knspace.fork() forked_knspace2 = knspace.fork()
现在,添加到`knspace`中的任何名称都将通过常规方式在`forked_knspace1`和`forked_knspace2`命名空间中可访问。然而,添加到`forked_knspace1`中的任何名称将无法从`knspace`或`forked_knspace2`中访问。对于`forked_knspace2`也是如此。
- keep_ref = False¶
是否应保留对存储对象的直接引用。若为
True,则使用直接对象;否则,在存在proxy_ref时使用该代理引用。默认为 False。
- class kivy.uix.behaviors.knspace.KNSpaceBehavior(knspace=None, **kwargs)[源代码]¶
基类:
object继承自该类的对象可以被命名,并随后添加到关联的命名空间
knspace中,通过该命名空间即可访问它们。请参阅
knspace 行为模块的文档以获取更多信息。- knsname¶
赋予此实例的名称。若已命名,该名称将被添加到关联的
knspace命名空间中,并指向此实例的 proxy_ref。命名后,可以通过例如 self.knspace.name 来访问此对象,其中 name 是该实例的给定名称。更多详情请参阅
knspace及模块描述。
- knspace¶
与此控件关联的命名空间实例,即
KNSpace。当使用knsname为此控件命名时,knspace命名空间会存储该控件。如果命名空间已通过
KNSpace实例设置,例如使用 self.knspace = KNSpace(),则返回该实例(使用 None 设置不算)。否则,如果knspace_key不为 None,我们会在存储于该实例的knspace_key属性所命名的属性中查找要使用的命名空间。即 object = getattr(self, self.knspace_key)。如果该对象具有`knspace`属性,则返回其值。否则,我们继续向上查找,例如使用`getattr(object, self.knspace_key)`,并寻找其`knspace`属性。
最后,如果我们得到的值为 None,或者
knspace_key本身就是 None,则返回默认的knspace命名空间。如果
knspace被设置为字符串 'fork',则knspace中的当前命名空间将通过KNSpace.fork()进行分叉,并将结果命名空间分配给此实例的knspace。请参阅模块示例以获取一个启发性的示例。rebind 和 allownone 均为 True。
- kivy.uix.behaviors.knspace.knspace = <kivy.uix.behaviors.knspace.KNSpace object>¶
默认的
KNSpace命名空间。更多详情请参阅KNSpaceBehavior.knspace。