将小部件添加到KV动态类的继承类的子级中

时间:2019-03-19 19:05:50

标签: python kivy kivy-language

如果我有一个动态定义的类,例如:

<Foo@BoxLayout>:
    orientation: "vertical"

    ...some other child widgets...

    BoxLayout:
        id: target
        orientation: "horizontal"

        ...other children...

我如何创建一个继承自此的类,唯一的变化是使用BoxLayout添加到id: target的附加小部件?

我试图将动态类更改为规则并在python中定义类:

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函数中的id是空的。

有什么方法可以在不重新定义整个类的情况下完成此操作吗?

编辑:

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

这是无法正常工作的完整示例

2 个答案:

答案 0 :(得分:1)

执行Python代码后,.kv文件中的代码将初始化。

因此,您的EditedFoo(Foo)将首先从Python代码继承Foo(BoxLayout),然后将重新声明Foo文件中的.kv

最好的方法是将Foo(BoxLayout)的初始属性放在Python代码中,然后在Foo中继承.kv,例如<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

通过这种方式,您可以在EditedFoo继承的.kv中使用Foo类。

enter image description here

答案 1 :(得分:1)

.kv代码实现了用Python创建的类,因此可以理解,它将在构造函数完成执行后添加,因此id在构造函数中为空,一种技巧是使用Clock来调用函数渲染整个窗口后一会儿,因为那时id不会为空:

# ...
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)
相关问题