I am new to python and have a task to take input from a listbox and create radiobuttons for each entry. In my code I am able to create the radio buttons but they don’t function when I click on them i.e. in this case they don’t print “hello” and the number i. Here’s the code:
def generateGraph():
w = Toplevel(bg = "grey")
w.resizable(0,0)
frameData = Frame(w, bg="grey", padx=10, pady=10)
frameData.grid(row = 0, column=0, pady = 1, padx = 1, sticky = N+E+S+W)
InputLabel = Label(frameData, text="Inputs:", bg="grey")
InputLabel.grid(row=1, column=0, padx=10, sticky=N+E+S+W)
OutputLabel = Label(frameData, text="Outputs:", bg="grey")
OutputLabel.grid(row=1, column=1, padx=10, sticky=N+E+S+W)
i=0
c=[]
inputVar = IntVar()
while(InputBox.get(i)):
c.append(Radiobutton(frameData, text=InputBox.get(i), variable=inputVar, value = i, background="grey", command= hello(i)))
c[i].grid(row = i+2, column = 0, sticky = W)
i=i+1
if makemodal:
w.focus_set()
w.grab_set()
w.wait_window()
def hello(i):
print("hello %d" %i)
Please help and thanks in advance.
The problem is that you’re calling
hello(i)at the time of construction of theRadiobutton, not storing something to be called later:Since
helloreturnsNone, you’re effectively storingcommand=None.You need to store a callable here, like
helloitself, (or alambdaorpartial, or whatever), not the result of calling it.For example:
Since you asked in the comments: Note that I used
partialrather thanlambda, because I want to bind in the value ofi, not close over the variablei. Otherwise, you’d end up with, e.g., 5 radio buttons all bound to the same variableiwith the value4. There are other ways around this—use an explicit factory, dolambda x=i: hello(x)instead oflambda: hello(i), etc. To me,partialseems like the clearest and most explicit, but your mileage may vary. Anyway, there are dozens of questions on SO about this, but the answer to Scope of python lambda functions and their parameters seems particularly clear.