Родитель виджета не сразу доступен в файле KV - PullRequest
0 голосов
/ 03 марта 2019

В моем 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 и поместить его в init для класса Foo?

1 Ответ

0 голосов
/ 04 марта 2019

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