0

I want to create tkinter buttons in bulk by using a for loop and the exec function but when i set the command it keeps on calling the function for the last piece in my database

for i in FirstFloor:
    exec('room_%d = CreateRoom(FirstFloor[i]["name"])'%index)
    exec('lbl_%d = Button(window, text=FirstFloor[i]["name"], command=lambda: move(FirstFloor[i]["x"], FirstFloor[i]["y"]), bg="light grey")'%index)
    exec('lbl_%d.grid(column=FirstFloor[i]["x"], row=FirstFloor[i]["y"], columnspan=FirstFloor[i]["xspan"], rowspan=FirstFloor[i]["yspan"])'%index)
    if FirstFloor[i]["locked"] == True:
        exec('lbl_%d.config(state="disabled", bg="red")'%index)
    index += 1

When i run this piece of code and click a button no matter which button i press it keeps going to same object

krmckone
  • 315
  • 3
  • 8
Barty 200YT
  • 34
  • 10
  • Could you paste your code in the question as a code snippet, as opposed to free text, it will be easier for us to read and interpret. – Mark Stratmann Oct 22 '19 at 17:08
  • 2
    Since you're asking for help debugging, it's worth mentioning that exec() makes debugging more complicated (see https://stackoverflow.com/questions/1933451/why-should-exec-and-eval-be-avoided), so you'll save yourself time/headaches by not using it unless you really have to. – mRotten Oct 22 '19 at 17:09
  • I used exec because i have over 30 objects in FirstFloor and it saves me a lot of time than writing all the variables out – Barty 200YT Oct 22 '19 at 17:12
  • You really shouldn't use `exec`. It makes the code harder to understand and harder to debug. Just use a dictionary or list to store all of your button references. – Bryan Oakley Oct 22 '19 at 17:49
  • There is no reason to use `exec()` unless you know exactly how it works and how to use it I would avoid. It is 100% possible to do this without `exec()`. – Mike - SMT Oct 22 '19 at 18:31

2 Answers2

1

Change this:

command=lambda: move(FirstFloor[i]["x"]

to this:

command=lambda i=i: move(FirstFloor[i]["x"]
Paul M.
  • 10,481
  • 2
  • 9
  • 15
1

You can create buttons in bulk without exec. You can use a list, dict or tuple. I typically use a list.

By using a list we can reference the index to interact with the button.

Example:

import tkinter as tk

root = tk.Tk()
button_list = []


def do_something(some_value):
    print(button_list[some_value]['text'])


for i in range(10):
    button_list.append(tk.Button(root, text='Button {}'.format(i+1), command=lambda i=i: do_something(i)))
    button_list[-1].grid(row=i, column=0)

root.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79