macson taylor
macson taylor

Reputation: 181

Python : How to remove widget in kivy

I have two file demo.py and demo.kv.
when i run demo.py after click on menu then shows +Add more button.When i click on +Add more button then three row add dynamic because i am using loop there.Every time add three row dynamic
But can anyone tell me when i add new row then how to remove previous three row?
Every time should be show only 3 new row and previous row should be delete.I am using code

def add_more(self):
    self.remove_widget(Row())
    for x in range(0, 3):
        self.row_count += 1
        self.add_widget(Row(button_text=str(self.row_count)))

demo.py

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.uix.popup import Popup

Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)

class User(Popup):
    total_value = ObjectProperty(None)

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

    def add_more(self):
        self.ids.rows.add_more()


class Row(BoxLayout):
    col_data = ListProperty(["?", "?", "?", "?", "?"])
    name = ObjectProperty(None)
    button_text = StringProperty("")
    col_data3 = StringProperty("")
    col_data4 = StringProperty("")

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


class Rows(BoxLayout):
    row_count = 0

    def __init__(self, **kwargs):
        super(Rows, self).__init__(**kwargs)
        self.add_more()

    def add_more(self):
        self.remove_widget(Row())
        for x in range(0, 3):
            self.row_count += 1
            self.add_widget(Row(button_text=str(self.row_count)))


class rv(BoxLayout):
    data_items = ListProperty([])
    mode = StringProperty("")

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


    def add(self):
        self.mode = "Add"
        popup = User()
        popup.open()


class MainMenu(BoxLayout):
    content_area = ObjectProperty()

    def display(self):
        self.rv = rv()
        self.content_area.add_widget(self.rv)

class demo(App):

    def build(self):
        return MainMenu()


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

demo.kv

<Row>:
    size_hint_y: None
    height: self.minimum_height
    height: 40

    Button:
        text: root.button_text
        size_hint_x: None
        top: 200

    TextInput:
        id : name
        text: root.col_data3
        width: 300
    TextInput:
        id: number_input
        text: root.col_data4
        width: 300
        input_filter: 'int'


<Rows>:
    size_hint_y: None
    height: self.minimum_height
    orientation: "vertical"

<User>:
    id: user
    BoxLayout:
        orientation: "vertical"
        padding : 20, 5


        BoxLayout:
            orientation: "horizontal"
            #padding : 10, 10
            spacing: 10, 10
            size: 450, 40
            size_hint: None, None

            Label:
                size_hint_x: .2
                text: "Number"
                text_size: self.size
                valign: 'bottom'
                halign: 'center'

            Label:
                size_hint_x: .4
                text: "name"
                text_size: self.size
                valign: 'bottom'
                halign: 'center'

            Label:
                size_hint_x: .4
                text: "Value"
                text_size: self.size
                valign: 'bottom'
                halign: 'center'

        ScrollView:
            Rows:
                id: rows


        BoxLayout:
            orientation: "horizontal"
            size_hint_x: .2
            size_hint_y: .2

            Button:
                text: "+Add More"
                on_press: root.add_more()

<rv>:
    BoxLayout:
        orientation: "vertical"

        Button:
            size_hint: .25, .03
            text: "+Add"
            on_press: root.add()

        GridLayout:
            size_hint: 1, None
            size_hint_y: None
            height: 25
            cols: 3

        BoxLayout:
            orientation: "vertical"


<MenuButton@Button>:
    text_size: self.size
    valign: "middle"
    padding_x: 5
    size : (100, 40)
    size_hint : (None, None)
    background_color: 90 , 90, 90, 90
    background_normal: ''
    color: 0, 0.517, 0.705, 1
    border: (0, 10, 0, 0)

<MainMenu>:
    content_area: content_area

    BoxLayout:
        orientation: 'vertical'
        spacing : 10

        BoxLayout:
            canvas.before:
                Rectangle:
                    pos: self.pos
                    size: self.size

            size_hint_y: 2

            MenuButton:
                text: 'Menu'
                size : (50, 12)
                on_release: root.display()

        BoxLayout:
            id: content_area
            size_hint_y: 30

Upvotes: 2

Views: 8753

Answers (1)

FJSevilla
FJSevilla

Reputation: 4513

remove_widget must receive as argument the instance of the child widget to be removed. Since you can get widget's children using its children attribute, to remove the previous three rows you can do the following:

    def add_more(self):
        if self.children:
            for child in self.children[:3]:
                self.remove_widget(child)

        for x in range(0, 3):
            self.row_count += 1
            self.add_widget(Row(button_text=str(self.row_count)))

However, it's simpler to use clear_widgets method:

def add_more(self):
    self.clear_widgets(self.children[:3])
    for x in range(0, 3):
        self.row_count += 1
        self.add_widget(Row(button_text=str(self.row_count)))

Since you actually delete all the rows in the BoxLayout, you can do:

    def add_more(self):
        self.clear_widgets()
        for x in range(0, 3):
            self.row_count += 1
            self.add_widget(Row(button_text=str(self.row_count)))

Edit:

To reset the index simply disregard self.row_count and use the value returned by range:

    def add_more(self):
        self.clear_widgets()
        for x in range(1, 4):
            self.add_widget(Row(button_text=str(x)))

Upvotes: 8

Related Questions