Milfors
Milfors

Reputation: 1

Need help deleting kivy widgets

I have two main files.py and demo.kv. When executing the add_item function, I add 4 widgets (Label - 3 and MDRaisedButton - 1) and they form a string.

I want some way to press the 'delete this' button in a row to delete that particular row. I imagine I'd need some way to differentiate between these generated rows somehow but I haven't gotten that figured out yet either. I'd be extatic if someone had an elegant solution for this, as I've been stuck here for quite some time.

main.py

from kivy.lang import Builder
from kivy.core.window import Window

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDRaisedButton

Window.size = (500, 600)


finalPrice = []

finalItems = []

finalCounter = []

class MainApp(MDApp):

    def build(self):
        self.theme_cls.primary_palette = 'Blue'
        return Builder.load_file('demo.kv')


    def add_item(self, name, price, counter):


        mdRB = MDRaisedButton(text='delete this')
        mdRB.bind(on_press=self.delete_mdRB)

        self.root.ids.basketItems.add_widget(
            MDLabel(text=name, adaptive_height=True, adaptive_width=True)
        )
        self.root.ids.basketItems.add_widget(
            MDLabel(text=price, adaptive_height=True, adaptive_width=True, width=60, size_hint_x=None)
        )
        self.root.ids.basketItems.add_widget(
            MDLabel(text=counter, adaptive_height=True, adaptive_width=True, width=120, size_hint_x=None)
        )
        self.root.ids.basketItems.add_widget(
            mdRB
        )

    def delete_mdRB(self):
        for child in [child for child in self.root.ids.basketItems.children]:
            self.root.ids.basketItems.remove_widget(child)

        finalPrice.clear()
        print(finalPrice)

        finalItems.clear()
        print(finalItems)

        finalCounter.clear()
        print(finalCounter)

if __name__ == '__main__':
    MainApp().run()

demo.kv

#:import Factory kivy.factory.Factory

<Bases@Popup>
    auto_dismiss: True
    title: 'Item'

    background_normal: ""
    background_color: (26/255, 149/255, 184/255, .9)

    ScrollView:
        size: self.size

        GridLayout:

            size_hint_y: None
            height: self.minimum_height
            width: self.minimum_width

            cols: 3

            size: root.width * 0.5, root.height * 0.5
            row_default_height: 35
            row_force_default: True
            center: root.width / 1, root.height / 1

            Label:
                text: ''
            Label:
                text: ''
            Button:
                text: 'Close'
                font_size: 12
                on_release: root.dismiss()

            Label:
                text: 'Name'
                font_size: 12
                text_size: self.size
                halign: 'left'
                valign: 'middle'

            Label:
                text: 'Кол-во'
                font_size: 12
                text_size: self.size
                halign: 'right'
                valign: 'middle'
            Label:
                text: 'Basket'
                font_size: 12

            Label:
                text: f'Item 1 290$'
                font_size: 12
                text_size: self.size
                halign: 'left'
                valign: 'middle'
            AnchorLayout:
                anchor_x: 'right'
                TextInput:
                    id: name_input
                    multiline: 'False'
                    width: 60
                    size_hint_x: None
            Button:
                text: '+'
                on_press:
                    app.add_item('Item 1', '290', name_input.text)



            Label:
                text: f'Item 2 250$'
                font_size: 12
                text_size: self.size
                halign: 'left'
                valign: 'middle'

            AnchorLayout:
                anchor_x: 'right'
                TextInput:
                    id: name_input2
                    multiline: 'False'
                    width: 60
                    size_hint_x: None
            Button:
                text: '+'
                on_press:
                    app.add_item('Item 2', '250', name_input2.text)


BoxLayout:
    orientation: 'vertical'

    MDToolbar:
        title: 'Store'

    MDBottomNavigation:

        MDBottomNavigationItem:
            name: 'Items'
            text: 'Main'
            icon: 'home'

            MDBoxLayout:
                orientation: 'vertical'
                pos_hint: {'center_y':0.5}
                adaptive_height: True
                spacing: 2

                MDRaisedButton:
                    text: 'Items'
                    pos_hint: {"center_x":.5}
                    width: dp(250) + (self.ids.lbl_txt.texture_size[0] - self.ids.lbl_txt.texture_size[0])
                    on_release: Factory.Bases().open()

        MDBottomNavigationItem:
            name: 'Basket'
            text: 'Basket'
            icon: 'basket'

            ScrollView:
                size: self.size

                GridLayout:
                    size_hint_y: None
                    height: self.minimum_height
                    width: self.minimum_width

                    size: root.width * 0.5, root.height * 0.5
                    row_default_height: 35
                    row_force_default: True
                    center: root.width / 1, root.height / 1

                    id: basketItems
                    cols: 4
                    spacing: 4

Upvotes: 0

Views: 40

Answers (1)

John Anderson
John Anderson

Reputation: 38822

A Convenient way to do this is to put everything that you want to delete at one time into a single widget, so you can just delete that single widget. In your case, that single widget can be a BoxLayout that contains your three Labels and the Button. Then by using another BoxLayout instead of a GridLayout inside the ScrollView, each row can become a single BoxLayout. So changing the kv to use a BoxLayout:

    MDBottomNavigationItem:
        name: 'Basket'
        text: 'Basket'
        icon: 'basket'

        ScrollView:

            BoxLayout:
                orientation: 'vertical'
                size_hint_y: None
                height: self.minimum_height
                center: root.width / 1, root.height / 1
                id: basketItems
                spacing: 4

Then, the add_item() method can just add a BoxLayout to the basket and the delete_mdRB() can just delete that BoxLayout:

def add_item(self, name, price, counter):

    box = MDBoxLayout(adaptive_height=True)
    mdRB = MDRaisedButton(text='delete this')
    mdRB.bind(on_press=partial(self.delete_mdRB, box))  # pass the box to be removed

    box.add_widget(
        MDLabel(text=name, adaptive_height=True, adaptive_width=True)
    )
    box.add_widget(
        MDLabel(text=price, adaptive_height=True, adaptive_width=True, width=60, size_hint_x=None)
    )
    box.add_widget(
        MDLabel(text=counter, adaptive_height=True, adaptive_width=True, width=120, size_hint_x=None)
    )
    box.add_widget(
        mdRB
    )
    self.root.ids.basketItems.add_widget(
        box
    )

def delete_mdRB(self, box, button):
    box.parent.remove_widget(box)
    # for child in [child for child in self.root.ids.basketItems.children]:
    #     self.root.ids.basketItems.remove_widget(child)

    finalPrice.clear()
    print(finalPrice)

    finalItems.clear()
    print(finalItems)

    finalCounter.clear()
    print(finalCounter)

Upvotes: 0

Related Questions