Delicious_pie
Delicious_pie

Reputation: 49

Kivy Creating Buttons Dynamically and Accessing them

So I have been trying to write a kivy program, which first uses another py file to read latin sentences from a file, then dynamically create buttons for each sentence, when one of the buttons is clicked, it should delete itself. I was sucsessfull trying to create buttons dynamically, but I could'nt make them delete themselfs. The problem is if I create a Object property, declare it in kv file and bind it with the id, I can assign a function for on_release. But I want this to happen automatically, and if I have 15 sentences, I dont want to declare the Objectproperty 15 times in the kv file. I have tried creating a list, then creating number of sentences items in it, and making those items a objectproperty. But then I get a error when declaring it in the kv file. Here is my code:

import kivy
from Nils_Programm_verkürzt import lektionstextlesen
from kivy.app import App
from kivy.uix.label import Label, Widget
from kivy.uix.button import Button
from kivy.properties import (
    NumericProperty, ReferenceListProperty, ObjectProperty, StringProperty, ListProperty
)
from kivy.lang import Builder


##################

#INPUT FILE:
Inputfile = 'Lektionstext15.txt'

ReturnTuple = []
ReturnTuple = lektionstextlesen(Inputfile)
Satzliste = ReturnTuple[0]
Worterliste = ReturnTuple[1]


kv = """
#:import Button kivy.uix.button.Button
<Testwidget>:
    canvas:
        Rectangle:
            pos: 0, self.center_y
            size: self.width, 10
        Rectangle:
            pos: self.pos
            size: self.size
            source: 'background.png'"""

add = """
    Buttons: Buttons
    Button:
        id : Buttons[{index}]
        text: str(root.Satzliste[{index}])
        center_x: root.width / 2
        top: root.top - 100 - {num}
        font_size: 30
        size: self.texture_size
        on_release: root.callback({index})
"""

#addf = add.format(num=0)

for i in range(len(Satzliste)):

    addf = add.format(index = i, num=(i*50))

    kv = f"{kv}{addf}"

#kv = f"{kv}{addf}"

#print(kv)
Builder.load_string(kv)

class Testwidget(Widget):
    Satzliste = StringProperty()
    Worterliste = StringProperty()
    ReturnTuple = []
    ReturnTuple = lektionstextlesen(Inputfile)
    Satzliste = ReturnTuple[0]
    Worterliste = ReturnTuple[1]

    Buttons = []
    for i in range(len(Satzliste)):
     Buttons.append(ObjectProperty(None))

    def callback(self, m):
        self.remove_widget(self.Buttons[m])

    pass

class GuiApp(App):
    def build(self):
        return Testwidget()


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

Upvotes: 0

Views: 551

Answers (1)

Yummaddo
Yummaddo

Reputation: 11

I did not fully understand what you want to do but I don't really like the way you create the button; it's also possible, but it's better for me to create a custom class for the object button that stores them and the main window.

Like this:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

from kivy.properties import (
    NumericProperty, ReferenceListProperty, ObjectProperty, StringProperty, ListProperty
)
from kivy.lang import Builder

kv = """
#:import hex kivy.utils.get_color_from_hex

<CustomButton>:
    size_hint_x: 0.8
    size_hint_y: 0.2
    text: root.name
    center_x: root.width / 2
    font_size: 30
    on_release: root.callback(self,self.parent)


<Testwidget>:
    id: object_for_scroll
    size_hint_y: 2
    cols: 1

<Main>:
    canvas:
        Color:
            rgba: hex('#777576')
        Rectangle:
            pos: self.pos
            size: self.size
    size_hint: 1,1
    ScrollView:
        id: buttons_layout
        size_hint_x: 0.9
        size_hint_y: 0.82
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}

"""
class Main(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.buttons_pool = Testwidget()


        #INPUT FILE:
        # here you can read information from a file and create buttons with specific names

        text = "name\n"*20
        # you can go for taple or list its dosnt mater
        for index,but_text in enumerate(text.split("\n")):
            but = CustomButton() # create obj and set his parameters of text ( also you can set any parameter )
            setattr(but, "name", but_text+str(index)) # index is name for example, you can put any one

            # add into the pool
            setattr(self.buttons_pool,"size_hint_y", index//5+1)
            self.buttons_pool.add_widget(but)


        self.ids.buttons_layout.add_widget(self.buttons_pool)


class CustomButton(Button):
    name = StringProperty()
    def callback(self, widget ,pool):
        pool.remove_widget(widget)


class Testwidget(GridLayout):
    pass
 

class GuiApp(App):
    def build(self):
        Builder.load_string(kv)

        return Main()


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

I showed an example of how it is possible to remove buttons when creating their class, the sizes, how and where the widgets will be placed and what they will be does not matter.

Upvotes: 1

Related Questions