1

So, I've got a list with entries that look like this:

Option1  Placeholder1    2   Placeholder2    0      
Option2  Placeholder1    4              
Option3  Placeholder1    2   Placeholder2    -2   Placeholder3    6

I have a listbox of the Options and a button that creates a new window with the values for the selected Option. What I want to do is to create n number of buttons when this new window is created, where n is the number of values of the selected Options (i.e. 2, 1 and 3 for Options 1 through 3, respectively). I want it to look something like this:

Option1
Placeholder1    [button1 containing value=2]
Placeholder2    [button2 containing value=0]

... which is of course quite simple if I just assign a button for the maximum number of n that I know will be present, but I'm wondering if there's a way to do it more arbitrarily. Obviously the same problem applies to the arbitrary number of Labels I would need to use for the value names (the 'PlaceholderX's) as well.

I've been trying to do some reading on this type of thing, variable variables, etc., and it seems it's a very big NO-NO most (if not all) of the time. Some advocate the use of dictionaries, but I don't really get how that's supposed to work (i.e. naming variables from entries/values in a dict).

Is this something that can (and should) be done, or am I better off just creating all the buttons manually?

[EDIT: added code]

from tkinter import *
import csv

root = Tk()
root.wm_title("RP")

listFrame = Frame(root, bd=5)
listFrame.grid(row=1, column=2)

listbox1 = Listbox(listFrame)
listbox1.insert(1, "Option1")
listbox1.insert(2, "Option2")
listbox1.insert(3, "Option3")
listbox1.pack()

infoFrame = Frame(root, bd=5)
infoFrame.grid(row=1, column=3)

info_message = Message(infoFrame, width=300)
info_message.pack()

# Read stats from file
stat_file = open('DiceTest.csv', 'rU')
all_stats = list(csv.reader(stat_file, delimiter=';'))


def list_selection(event):
    # gets selection and info/stats for info_message
    index = int(listbox1.curselection()[0])
    stats = all_stats[index]

    infotext = str(stats[0])  # just the name
    for n in range(int((len(stats)-2)/2)):  # rest of the stats
        infotext += ('\n' + str(stats[n*2 + 2]) + '\t' + str(stats[n*2 + 3]))

    info_message.config(text=infotext)

listbox1.bind('<ButtonRelease-1>', list_selection)

def load():
    top = Toplevel()
    top.geometry('300x100')

    index = int(listbox1.curselection()[0])
    stats = all_stats[index]

    # some way to create arbitrary buttons/labels here (?)

load_button = Button(root, text='Load', command=load)
load_button.grid(row=2, column=2)

root.mainloop()

Oh, and every button should have the same command/function, which reduces whatever value currently is in the button by 2.

erikfas
  • 4,357
  • 7
  • 28
  • 36

2 Answers2

3

Figured it out! Creating the widgets dynamically with a dictionary worked just fine, but calling the correct widget on the various button presses was more difficult. This is what I had:

buttons = dict()
for k in range(len(info)):
    buttons[k] = Button(top, text=info[k], command=lambda: my_function(buttons[k]))

... which would work, but all button presses would call the function with the last created button as the target. All that was needed was a few extra characters in the command part of the buttons:

buttons = dict()
for k in range(len(info)):
    buttons[k] = Button(top, text=info[k], command=lambda a=k: my_function(buttons[a]))

... which I assume works because it somehow stores the value of k inside a rather than taking the last known value of k, i.e. equivalent to the last created button. Is this correct?

erikfas
  • 4,357
  • 7
  • 28
  • 36
2

You can store Buttons in a list:

from tkinter import *
master = Tk()
buttons = []
n = 10
for i in range(n):
    button = Button(master, text = str(i))
    button.pack()
    buttons.append(button)
master.mainloop()
User
  • 14,131
  • 2
  • 40
  • 59
  • Okay, but how do I, when calling the button function (same for all buttons) make sure the function gets the correct button handle? Do I somehow call the function with an index in the list of buttons? – erikfas Feb 26 '14 at 07:37
  • It would have been better to ask that question more explicitly. The canonical version is here: https://stackoverflow.com/questions/10865116/tkinter-creating-buttons-in-for-loop-passing-command-arguments – Karl Knechtel Aug 16 '22 at 01:56