how do I pass self.selected(i)? – Python
Question:
from tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.grid()
self.grid_data_table = ["NONE"]
self.D_Text = " "
self.a = 0
self.b = 0
for i in range(1,100 + 1):
self.grid_data_table.extend([i])
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda: self.selected(i))
self.a = self.a + 1
self.grid_data_table[i].grid(row=self.b, column=self.a)
#self.grid_data_table[i]["text"] = str(i) # testing only
if self.a == 10:
self.b = self.b + 1
self.a = 0
def selected(self, num):
print("Loaded Button:", num)
root = Tk()
app = App(root)
root.mainloop()
anyhow, When I run this, I get the grid of 100 buttons in a 10×10 square, just the way I want, but the issue is command=self.selected(i) seems to make all of the buttons do self.selected(100) and no 1,2,3,4… 100. am I doing something wrong here?
I wanted to use a “list” or “array” to do this because it is so much easier than writing 100 buttons out.
Answers:
You can do the following
command=lambda i=i: self.selected(i)
You are creating what is called a closure and when your command executes it captures the value of i
at that point (hence always 100), not when the button is created. If you assign i to another local variable then you capture its value at the point the Button
is created.
Try changing this line,
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda: self.selected(i))
to
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda i=i: self.selected(i))
The problem is the current code is closing over the variable i, so in each command it is equal to whatever it is set to outside the function. Adding the i=i
before creates a locally scoped variable i which does not change as the loop iteration continues.
from tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.grid()
self.grid_data_table = ["NONE"]
self.D_Text = " "
self.a = 0
self.b = 0
for i in range(1,100 + 1):
self.grid_data_table.extend([i])
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda: self.selected(i))
self.a = self.a + 1
self.grid_data_table[i].grid(row=self.b, column=self.a)
#self.grid_data_table[i]["text"] = str(i) # testing only
if self.a == 10:
self.b = self.b + 1
self.a = 0
def selected(self, num):
print("Loaded Button:", num)
root = Tk()
app = App(root)
root.mainloop()
anyhow, When I run this, I get the grid of 100 buttons in a 10×10 square, just the way I want, but the issue is command=self.selected(i) seems to make all of the buttons do self.selected(100) and no 1,2,3,4… 100. am I doing something wrong here?
I wanted to use a “list” or “array” to do this because it is so much easier than writing 100 buttons out.
You can do the following
command=lambda i=i: self.selected(i)
You are creating what is called a closure and when your command executes it captures the value of i
at that point (hence always 100), not when the button is created. If you assign i to another local variable then you capture its value at the point the Button
is created.
Try changing this line,
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda: self.selected(i))
to
self.grid_data_table[i] = Button(frame, text=self.D_Text, font="bold", command=lambda i=i: self.selected(i))
The problem is the current code is closing over the variable i, so in each command it is equal to whatever it is set to outside the function. Adding the i=i
before creates a locally scoped variable i which does not change as the loop iteration continues.