简体   繁体   中英

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()

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM