窗口小部件父级在KV文件中不立即可用

时间:2019-03-03 20:12:24

标签: python kivy kivy-language

我在KV文件中有一个规则,该类称为Foo,它继承自Widget类,该类在我的python文件中创建了实例:(已删除了最不相关的细节)

在python中:

Class Foo(Widget):
    x_coord = NumericProperty()
    y_coord = NumericProperty()

在Kv中:

<Foo>:
    pos: self.x_coord + self.parent.bar, self.y_coord() + self.parent.barbar

但是当我实例化该类时:

new_foo = Foo()
new_foo.x_coord = 7
new_foo.y_coord = 10
[do some more stuff with it]

<a parent widget>.add_widget(new_foo)

我收到一个错误,说type object NoneType has no attribute bar

在我看来,该KV文件在实例化该类后立即尝试应用该规则,但它尚未获得父项,因为尚未将其添加到任何内容。我什至尝试向Foo添加一个名为parent的临时子类,该子类具有我所引用的所有属性的工作值,但这确实阻止了错误,但是我立即得到了一个新的子类,因为kivy无法覆盖临时类以添加实际的父类

我该如何解决?有没有一种方法可以通过父母作为参数?还是我应该在python中写出规则,然后将其放在Foo类的init中?

1 个答案:

答案 0 :(得分:0)

parent也是一个属性。这意味着您可以创建on_parent方法来设置其使用属性的方式:

from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout


class Parent(FloatLayout):
    bar = NumericProperty(20)


class Child(Button):
    def on_parent(self, obj, parent):
        self.pos = (parent.bar, parent.bar)


class MyApp(App):
    def build(self):
        parent = Parent()
        child = Child(text="Test", size_hint=(None, None))
        parent.add_widget(child)
        return parent


if __name__ == '__main__':
    MyApp().run()

如果要在更改父级属性时做出反应,可以使用on_parent方法将方法绑定到父级属性:

from functools import partial

from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout


class Parent(FloatLayout):
    bar = NumericProperty(20)


class Child(Button):
    def on_parent(self, obj, parent):
        self.pos = (parent.bar, parent.bar)
        parent.bind(bar=self.update_pos)

    def update_pos(self, obj, bar):
        self.pos = (bar, bar)


class MyApp(App):
    def build(self):
        parent = Parent()
        child = Child(text="Test", size_hint=(None, None))
        parent.add_widget(child)
        Clock.schedule_once(partial(self.change_parent_bar, parent), 3)
        return parent

    def change_parent_bar(self, parent, dt):
        parent.bar = 50


if __name__ == '__main__':
    MyApp().run()