1

I'm trying to create some buttons dynamically for Python and Kivy based on an external file.

So far, I managed to web scrape the file, read it and create widgets with it. The problem is that I need those widgets to have a unique var name and I can't see a way to achieve this.

def build(self):
    #main layout
    menu_box = BoxLayout(orientation="horizontal")
    #web scraping
    try:
        WebLeida = request.urlopen("http://coznothingisforever.webs.com/Yoloplanner/Yoloplanner.txt").read().decode('utf8')
        WebParsed = ast.literal_eval(WebLeida)
        #for each item
        for i in WebParsed:
            #create a button
            boton = Button(font_size=16,
                            size_hint_y=None,
                            height=100,
                            text=i["dia"] + " - " + i["hora"])
            #bind the events
            boton.bind(print("testing"))
            #add the new created button to the layout
            menu_box.add_widget(boton)
    except:
        print("Something went wrong")
    #run the main layout
    return menu_box

The problem with this is that all the buttons would be named "boton", so when I need to use specific functions like boton.bind the program won't know which one to use.

This is the desired outpost, but with unique var names: enter image description here

Any suggestions?
Also, is web scraping the best way to achieve this?

cdlane
  • 40,441
  • 5
  • 32
  • 81
Saelyth
  • 1,694
  • 2
  • 25
  • 42
  • [This](http://stackoverflow.com/questions/35856891/how-can-i-make-a-lot-of-buttons-at-dynamic-in-kv-language/35867156#35867156) might be helpful for you. – jligeza Mar 10 '16 at 10:42
  • it is a bit brutish but have you tried inside the for: `exec("self.boton"+str(i)) = ...` ? – Mixone Mar 11 '16 at 17:53

2 Answers2

2

Do you care about what the id is? If its just uniqueness then

import uuid
id = str(uuid.uuid4())

If you care about what the id is could do

id_template = 'button_id_{0}'
count = 1
for i in WebParsed:
   button_id = id_template.format(count)
   count += 1
quikst3r
  • 1,783
  • 1
  • 10
  • 15
1

I don't know why no one posted this as an answer even if it is in python tag. Every widget in kivy is an object, so it's there when you create it and you don't have to use a variable directly, just Button(...) in a line for example. Therefore it's in kv file so easy to design your app in this way:

<Root_widget>:
    SomeWidget:
        Button_1:
        ...
        Button_N:

No variable, however if you want, you can pass id to your widget, which are then collected to ids dictionary. And there comes something similar as ids. You can freely create your own dictionary and add every Button you like to it in a way like this:

my_buttons['new_button'] = Button(font_size=16, size_hint_y=None, height=100,
                                  text=i["dia"] + " - " + i["hora"])

If you bind, it'll be like <xyz object at somewhere>.bind() and in an example it'd look like this:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from functools import partial

class Box(BoxLayout):
    buttons={}
    def __init__(self, **kw):
        super(Box, self).__init__(**kw)
        for i in range(10):
            self.buttons[str(i)]=Button(text=str(i))
            self.add_widget(self.buttons[str(i)])
            self.buttons[str(i)].bind(on_release=partial(self.ping, str(i)))
    def ping(self, *arg):
        print 'test',str(arg)
class My(App):
    def build(self):
        return Box()
My().run()
Peter Badida
  • 11,310
  • 10
  • 44
  • 90