小部件父级在KV文件中不能立即使用

问题描述 投票:0回答:1

我在我的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文件试图在实例化类时立即应用规则,但它还没有父级,因为它还没有被添加到任何东西。我甚至尝试将一个名为parent的临时子类添加到Foo中,该子类具有我引用的所有属性的工作值,这确实停止了错误,但我立即得到了一个新的,因为kivy无法覆盖临时类以添加实际的父级。

我该如何解决这个问题?有没有办法将父母作为参数传递?或者我应该在python中写出规则并将其放在Foo类的init中?

python kivy kivy-language
1个回答
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()
© www.soinside.com 2019 - 2024. All rights reserved.