在 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.

中使用EditedFooclass

.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)