[Python] Kivy: RecycleView calls __init__ before data is set, and seems to reset size to...

Discussão em 'Python' iniciado por Stack, Março 3, 2025.

  1. Stack

    Stack Membro Participativo

    I have a RecycleView. Its viewclass is a class that extends Button. An initial basic example I made is working, except 1. some initializiation data is not displayed and 2. the buttons are resized (to (100, 100) — I’m guessing that’s a Button size default).

    class InventoryIngredientButton(Button):
    count = NumericProperty(None)
    display_count = StringProperty(None)

    def __init__(self, inventory_ingredient: InventoryIngredient = ing1, **kwargs):
    print("init is being called")
    super().__init__(
    background_normal=inventory_ingredient.ingredient.icon_img,
    text=inventory_ingredient.ingredient.display_name,
    size_hint=(None, None),
    size=(200, 200),
    **kwargs)

    def use(self):
    self.count -= 1
    self.display_count = str(self.count)

    def on_count(self, instance, value):
    # print size for debugging
    print("count is %s and size is %s" % (value, self.size))
    if value == 0:
    self.disabled = True

    # for debugging
    def on_size(self, instance, value):
    print("Size changed to value %s for button %s" % (value, self.count))




    class RV(RecycleView):
    def __init__(self):
    super().__init__()

    # 1. count is respected, inventory_ingredient is not:
    # 2. If you add “’size’: (200, 200)” to the dictionaries then buttons aren’t resized:
    self.data = [{'inventory_ingredient': ing2, 'count': 6}, {'count': 3, 'inventory_ingredient': ing1}]


    .tutorial_listview.kv file:

    <InventoryIngredientButton>
    pos: self.x, self.y
    pos_hint: None, None
    count: 1
    on_press: root.use()

    Label:
    text: str(root.count)
    pos: root.x-10,root.y-10
    pos_hint: None, None

    <RV>:
    viewclass: 'InventoryIngredientButton'
    RecycleBoxLayout:
    rows: 2
    cols: 5
    size_hint: 1, 1
    pos_hint: 0, 0


    Runner included for completeness:

    class RecycleTutorialApp(App):
    def build(self):
    return RV()


    if __name__ == "__main__":
    Builder.load_file('tutorial_listview.kv')
    RecycleTutorialApp().run()


    The print logs indicate that the buttons are initialized with default values. Then, when self.data is set, count is overwritten to the displayed value. However, unless I explicitly set size, size=(100,100) seems to reset next and resizes the button. inventory_ingredient is also ignored because __init__ has already been called.

    Logs show init is called, then count is changed, then size:

    init is being called and type is Lemon (Lemon is the default)
    Size changed to value [200, 200] for button None
    count is 1 and size is [200, 200]
    count is 0 and size is [200, 200]
    Size changed to value [100, 100] for button 0
    init is being called and type is Lemon
    Size changed to value [200, 200] for button None
    count is 1 and size is [200, 200]
    Size changed to value [100, 100] for button 1


    I suspect that changing inventory_ingredient to an ObjectProperty would allow it to get updated on-the-fly, but I didn’t want all of the automatically generated event listeners that would come with that because it shouldn't change post-initialization. And obviously I can also force size=(200,200) every time I change data. But both those solutions feel like a shallow workaround because I’m brand new to Kivy and lack a fuller understanding of the behavior that’s happening.

    PS In RV.__init__, I tried 1. setting self.data before calling super().__init__() and 2. passing super().__init__(data=data, **kwargs) but neither worked.

    Continue reading...

Compartilhe esta Página