Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

kivy access child id

Tags:

python

kivy

I want to access the id of the child to decide whether to delete the widget or not. I have the following code:

main.py

#!/usr/bin/kivy
# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout


class Terminator(BoxLayout):
    def DelButton(self):
        print("Deleting...")

        for child in self.children:
            print(child)
            print(child.text)

            if not child.id == 'deleto':
                print(child.id)
                #self.remove_widget(child)
            else:
                print('No delete')


class TestApp(App):
    def build(self):
        pass


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

test.kv

#:kivy 1.9.0

<Terminator>:
    id: masta
    orientation: 'vertical'

    Button:
        id: deleto
        text: "Delete"
        on_release: masta.DelButton()

    Button
    Button

Terminator

However when printing the id with: print(child.id), it always returns: None. Even though print(child.text) correct returns Delete or .

Question

  • Why does child.id not return deleto, but instead None?
  • How can I make a check that I don't delete the button with "Delete" on it, but delete all other buttons?
like image 988
NumesSanguis Avatar asked Dec 02 '25 00:12

NumesSanguis


1 Answers

As you can read in the documentation:

In a widget tree there is often a need to access/reference other widgets. The Kv Language provides a way to do this using id’s. Think of them as class level variables that can only be used in the Kv language.

Accesing ids from Python code is described here. Working example:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.button import Button

Builder.load_string("""
<Terminator>:
    id: masta
    orientation: 'vertical'

    MyButton:
        id: deleto

        button_id: deleto

        text: "Delete"
        on_release: masta.DelButton()

    MyButton
    MyButton
""")

class MyButton(Button):
    button_id = ObjectProperty(None)

class Terminator(BoxLayout):
    def DelButton(self):
        for child in self.children:
            print(child.button_id)       

class TestApp(App):
    def build(self):
        return Terminator()    

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

To skip deleting a button with "Delete" label you can examine its text property. Hovewer deleting from inside the loop will lead to the bugs, since some of the children will get skiped after the list you're iterating on will get altered:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in self.children:            
            self.remove_widget(child) # this will leave one child

You have to create a list of children to delete:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in [child for child in self.children]:            
            self.remove_widget(child) # this will delete all children

In your case:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in [child for child in self.children if child.text != "Delete"]:            
            self.remove_widget(child)
like image 115
Nykakin Avatar answered Dec 03 '25 13:12

Nykakin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!