Есть ли в kivy хук / функция для запуска после добавления виджета в дерево, например onComponentDidMount

#python #kivy

#python #kivy

Вопрос:

Я борюсь с созданием повторно используемых виджетов в kivy. В частности, проблема в том, что при запуске конструктора виджетов виджет еще не является частью дерева виджетов. Таким образом, у него не будет родительского элемента, и если свойства виджета, такие как size, label или size_hint, определены в файле kvlang для приложения, эти значения также недоступны в конструкторе для виджета.

Итак, мой вопрос в том, есть ли функция или хук, которые я могу запускать в виджете, когда виджет добавляется в дерево виджетов. Аналогично тому, как многие фреймворки html / javascript имеют, например, функцию «onComponentDidMount», которая вызывается после добавления виджета в DOM. Когда вызывается эта функция, в идеале ее свойства должны быть установлены из приложения kvlang builder / source, где оно использовалось, у него должны быть родительский и дочерний элементы и т. Д. На этом этапе вы можете внести последние изменения в дочерние элементы или сам виджет.

Комментарии:

1. У каждого виджета есть parent свойство, которое можно наблюдать. Возможно, вы могли бы привязаться к этому свойству.

2. Это звучит как хорошая идея. Я проверю. Спасибо!

Ответ №1:

Родительский наблюдаемый, подобный упомянутому Джоном Андерсоном, работает в некоторых случаях, но у меня был случай, когда некоторые элементы все еще не были инициализированы. Но для меня сработал Clock.schedule_once метод. Вы можете запланировать вызов функции один раз, и если вы сделаете это со временем 0, она будет запущена при следующем рендеринге экрана, после чего все виджеты будут инициализированы.

Так что это сработало для меня:

 from kivy.clock import Clock
from kivy.uix.stacklayout import StackLayout


class SelectBox(StackLayout):
    """An html style select box"""
    label = StringProperty('Select an option')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.value = None
        Clock.schedule_once(self.onWidgetInitialized)

    def onWidgetInitialized(self, *_args, **_kwargs):
        """Do stuff once the whole widget has been initialized."""