在 kv dynamic class 中将 Widget 添加到继承 class 的子项
Add Widget to child of inherited class in kv dynamic class
如果我有一个动态定义的 class,例如:
<Foo@BoxLayout>:
orientation: "vertical"
...some other child widgets...
BoxLayout:
id: target
orientation: "horizontal"
...other children...
如何创建一个继承自此的 class,唯一的变化是使用 id: target
添加到 BoxLayout
的附加小部件?
我试图将动态 classes 更改为规则并在 python:
中定义 classes
class Foo(BoxLayout):
pass
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.ids["target"].add_widget(<the widget I want to add>, index=0)
但是 __init__
函数(以及 on_parent
函数)中的 ids 为空。
有没有什么方法可以在不重新定义整个的情况下做到这一点class?
编辑:
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
kv = """
BoxLayout:
EditedFoo:
<Foo>:
orientation: "vertical"
BoxLayout:
id: target
orientation: "horizontal"
"""
class TestApp(App):
def build(self):
return Builder.load_string(kv)
class Foo(BoxLayout):
pass
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.ids["target"].add_widget(Button(text="hello"), index=0)
TestApp().run()
这是一个完整的验证示例,它不起作用
.kv
文件中的代码在 Python 代码执行后被初始化。
因此,您的 EditedFoo(Foo)
将首先从 Python 代码继承 Foo(BoxLayout)
,然后 .kv
文件中的 Foo
将被重新声明。
最好的方法是将Foo(BoxLayout)
的初始属性放在Python代码中,然后在.kv
中继承Foo
如<EditedFoo@Foo>
例如,
在.py
中:
class Foo(BoxLayout):
greeting = "hi"
在.kv
中:
<EditedFoo@Foo>
greeting: "Goodbye World"
Foo:
id: root_foo
Button:
text: root_foo.greeting
EditedFoo:
id: foo1
Label:
text: foo1.greeting
EditedFoo:
id: foo2
greeting: "Hello Another World"
Button:
text: foo2.greeting
这样就可以在.kv
继承Foo
.
中使用EditedFoo
class
.kv代码实现了Python中创建的class,所以可以理解为是在构造函数执行完后添加,因此构造函数中的ids为空,a诀窍是使用 Clock 在渲染整个 window 之后立即调用一个函数,因为在那一刻 ids 不会为空:
# ...
from kivy.clock import Clock
# ...
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.callback)
def callback(self, *args):
self.ids["target"].add_widget(Button(text="hello"), index=0)
如果我有一个动态定义的 class,例如:
<Foo@BoxLayout>:
orientation: "vertical"
...some other child widgets...
BoxLayout:
id: target
orientation: "horizontal"
...other children...
如何创建一个继承自此的 class,唯一的变化是使用 id: target
添加到 BoxLayout
的附加小部件?
我试图将动态 classes 更改为规则并在 python:
中定义 classesclass Foo(BoxLayout):
pass
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.ids["target"].add_widget(<the widget I want to add>, index=0)
但是 __init__
函数(以及 on_parent
函数)中的 ids 为空。
有没有什么方法可以在不重新定义整个的情况下做到这一点class?
编辑:
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
kv = """
BoxLayout:
EditedFoo:
<Foo>:
orientation: "vertical"
BoxLayout:
id: target
orientation: "horizontal"
"""
class TestApp(App):
def build(self):
return Builder.load_string(kv)
class Foo(BoxLayout):
pass
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.ids["target"].add_widget(Button(text="hello"), index=0)
TestApp().run()
这是一个完整的验证示例,它不起作用
.kv
文件中的代码在 Python 代码执行后被初始化。
因此,您的 EditedFoo(Foo)
将首先从 Python 代码继承 Foo(BoxLayout)
,然后 .kv
文件中的 Foo
将被重新声明。
最好的方法是将Foo(BoxLayout)
的初始属性放在Python代码中,然后在.kv
中继承Foo
如<EditedFoo@Foo>
例如,
在.py
中:
class Foo(BoxLayout):
greeting = "hi"
在.kv
中:
<EditedFoo@Foo>
greeting: "Goodbye World"
Foo:
id: root_foo
Button:
text: root_foo.greeting
EditedFoo:
id: foo1
Label:
text: foo1.greeting
EditedFoo:
id: foo2
greeting: "Hello Another World"
Button:
text: foo2.greeting
这样就可以在.kv
继承Foo
.
EditedFoo
class
.kv代码实现了Python中创建的class,所以可以理解为是在构造函数执行完后添加,因此构造函数中的ids为空,a诀窍是使用 Clock 在渲染整个 window 之后立即调用一个函数,因为在那一刻 ids 不会为空:
# ...
from kivy.clock import Clock
# ...
class EditedFoo(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.callback)
def callback(self, *args):
self.ids["target"].add_widget(Button(text="hello"), index=0)