I add FloatLayout widgets in a loop, but only the last one has a background

Question:

I created my own widget class and assigned a default background to it, in the python file, several are created in the loop, but the background image is only visible on the last one created, why is this happening? Here is the code:

Here is the working (incorrect) code I got from my application:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivymd.app import MDApp
import own_classes


KV = ("""
<NewFloatLayout>
    FloatLayout:
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'icons/events/event_back_panel.png'


""")


class NewFloatLayout(FloatLayout):
    pass

    def __init__(self, **kwargs):
        super(NewFloatLayout, self).__init__(**kwargs)


class TestApp(MDApp):

    def build(self):
        self.theme_cls.theme_style = 'Light'
        self.theme_cls.primary_palette = 'BlueGray'
        Builder.load_file("test.kv")
        Builder.load_string(KV)

    def on_start(self):
      events_filling()

def pass_funk():
    pass


# заполняет экран эвентов
def events_filling():
    app = App.get_running_app()
    events_dict = [{'date': '2023-02-25', 'date_time': '2023-02-25 05:20:00', 'description': 'pat cat', 'status':
        'active', 'time': '05:20:00', 'title': 'pat', 'event_key': '-NP3v5nCWQO-VsastQdA'},
{'date': '2023-03-18', 'date_time': '2023-03-18 00:29:00', 'description': 'drink beer', 'status': 'active', 'time':
    '00:29:00', 'title': 'drink beer', 'event_key': '-NQig0z4yKmHs0o2bSe-'},
{'date': '2023-04-23', 'date_time': '2023-04-23 15:20:00', 'description': 'eat meat', 'status': 'active', 'time':
    '15:20:00', 'title': 'eat meat', 'event_key': '-NP6a-RDO0nKwH794j_F'}]
    for i in events_dict:
        layout_for_event = NewFloatLayout()


        events_box_layout = app.root.ids['events_layout']


        title = own_classes.LabelButton(text=i['title'], size_hint=(.7, .3),
                                        pos_hint={"top": .95, "right": .8}, color=(.72, .39, 0, 1), halign="left", valign="top",
                                        font_size=16)
        title.bind(size=title.setter('text_size'), on_release=pass_funk)

        description = own_classes.LabelButton(text=i['description'], size_hint=(.7, .4),
                            pos_hint={"top": .65, "right": .8}, halign="left", valign="top", font_size=15)

        description.bind(size=description.setter('text_size'), on_release=pass_funk)


        date = Label(text=i['date'], size_hint=(.4, .3), color=(.6, .6, .6, 1),
                     pos_hint={"top": .3, "left": .5})
        time = Label(text=i['time'], size_hint=(.4, .3), color=(.6, .6, .6, 1),
                     pos_hint={"top": .3, "right": .8})

        copy_button = own_classes.ImageButton(source="icons/events/copy.png", size_hint=(.25, .3),
                                              pos_hint={"top": .95, "right": 1})

        copy_button.bind(on_release=pass_funk)

        done_button = own_classes.ImageButton(source="icons/events/done.png", size_hint=(.25, .3),
                                              pos_hint={"top": .65, "right": 1})

        done_button.bind(on_release=pass_funk)

        delete_button = own_classes.ImageButton(source="icons/events/delete.png", size_hint=(.25, .3),
                                                pos_hint={"top": .35, "right": 1})

        delete_button.bind(on_release=pass_funk)

        layout_for_event.add_widget(title)
        layout_for_event.add_widget(description)
        layout_for_event.add_widget(date)
        layout_for_event.add_widget(time)
        layout_for_event.add_widget(copy_button)
        layout_for_event.add_widget(done_button)
        layout_for_event.add_widget(delete_button)
        events_box_layout.add_widget(layout_for_event)



TestApp().run()

Here is the kv file:

#:import test test

ScrollView:
    pos_hint: {"top": .79, "left": 1}
    size_hint: 1, .79
    GridLayout:
        id: events_layout
        name: "events_layout"
        cols: 1
        size_hint_y: None
        pos_hint: {"top": 1, "left": .8}
        height: self.minimum_height
        row_default_height: '100dp'
        row_fource_default: True
Asked By: Stanislav Bobovych

||

Answers:

In your KV, you are defining NewFloatLayout as a FloatLayout that contains another FloatLayout. If it is not your intent to have a FloatLayout inside another FloatLayout, you can simply remove the extra FloatLayout, like this:

KV = ("""
<NewFloatLayout>
    canvas.before:
        Rectangle:
            pos: self.pos
            size: self.size
            source: 'icons/events/event_back_panel.png'
""")

If you do intend to have one FloatLayout inside another FloatLayout, then you just need to set the pos of the inside FloatLayout, like this:

KV = ("""
<NewFloatLayout>
    FloatLayout:
        pos: root.pos
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'icons/events/event_back_panel.png'
""")

Otherwise, the inside FloatLayout gets the default pos of (0, 0), and all three will be at the same position. Also note that the loop that adds widgets to the layout_for_event is adding widgets to the outside FloatLayout, not the second (or inside) FloatLayout, so the indside FloatLayout is essentially unused.

Answered By: John Anderson
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.