Я написал собственный виджет в Kivy. Мне нужно отобразить несколько тысяч экземпляров этого объекта виджета в сетке на экране киви. Это приводит к сбою системы, поэтому я заключаю GridLayout в RecycleView. Благодаря этому он будет рендериться немедленно и без каких-либо задержек. Отлично!
Раньше в функцию __init__() моего пользовательского виджета передавались позиционные аргументы, которые я использовал для настройки нескольких полей экземпляра, которые будут использоваться для определения того, что будет появляются (и как) в виджете. К сожалению, RecycleView заставил меня заменить позиционные аргументы свойствами Kivy. И я не могу получить доступ к значениям этих свойств в функции __init__() объекта.
Для простоты давайте рассмотрим этот минимальный пример проблемы, взятый из этот вопрос в списке рассылки Kivy.
Код: Выделить всё
#!/usr/bin/env python3
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty
kv = '''
:
# This class is used as the viewclass in the RecycleView
# The means this widget will be instanced to view one element of data from the data list.
# The RecycleView data list is a list of dictionaries. The keys in the dictionary specify the
# attributes of the widget.
Button:
text: root.left_text
on_release: print(f'Button {self.text} pressed')
Button:
text: root.right_text
on_release: print(f'Button {self.text} pressed')
BoxLayout:
orientation: 'vertical'
Button:
size_hint_y: None
height: 48
text: 'Add widget to RV list'
on_release: rv.add()
RV: # A Reycleview
id: rv
viewclass: 'TwoButtons' # The view class is TwoButtons, defined above.
scroll_type: ['bars', 'content']
bar_width: 10
RecycleBoxLayout:
# This layout is used to hold the Recycle widgets
default_size: None, dp(48) # This sets the height of the BoxLayout that holds a TwoButtons instance.
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height # To scroll you need to set the layout height.
orientation: 'vertical'
'''
class TwoButtons(BoxLayout): # The viewclass definitions, and property definitions.
left_text = StringProperty()
right_text = StringProperty()
print( "TwoButtons top" )
def __init__(self, **kwargs):
print( "self.left_text:|" +str(self.left_text)+ "|" )
super().__init__(**kwargs)
print( "self.left_text:|" +str(self.left_text)+ "|" )
class RV(RecycleView):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.data = [{'left_text': f'Left {i}', 'right_text': f'Right {i}'} for i in range(2)]
def add(self):
l = len(self.data)
self.data.extend(
[{'left_text': f'Added Left {i}', 'right_text': f'Added Right {i}'} for i in range(l, l + 1)]
)
class RVTwoApp(App):
def build(self):
return Builder.load_string(kv)
RVTwoApp().run()

Кнопки в графическом интерфейсе отображаются с текстом Left 0 и Left 1 по желанию, но попытка получить доступ к их значениям из __init__() приводит к пустая строка (
Код: Выделить всё
self.left_text:||Две кнопки Класс имеет два свойства Kivy:
- StringProperty left_text и
StringProperty right_text
Проблема в том, что значением свойства left_text является пустая строка внутри __init__()
Рассмотрим следующее выполнение приведенной выше программы:
Код: Выделить всё
user@buskill:~/tmp/rv$ python3 rv.py
[INFO ] [Logger ] Record log in /home/user/.kivy/logs/kivy_24-03-17_23.txt
[INFO ] [Kivy ] v2.1.0
[INFO ] [Kivy ] Installed at "/home/user/.local/lib/python3.9/site-packages/kivy/__init__.py"
[INFO ] [Python ] v3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110]
...
[INFO ] [Text ] Provider: sdl2
[INFO ] [Base ] Start application main loop
[INFO ] [GL ] NPOT texture support is available
self.left_text:||
self.left_text:||
self.left_text:||
self.left_text:||
Более того, если вы нажмете кнопку «Добавить виджет в список RV», чтобы добавить третий ряд кнопок с текстом «Добавлено слева 2» и «Добавлено справа 2», то следующие новые строки будут print()
Подробнее здесь: https://stackoverflow.com/questions/781 ... lf-on-init