Iterating through buttons in tkinter
Question:
I try to create buttons in tkinter using a loop.
def bulkbuttons():
i = 0
x = 0
buttons=[]
while x < 10:
buttons.append('button' + str(x))
x+=1
while i < 10:
buttons[i]=Button(window,text=str(i), width=12,borderwidth=1, relief='raised', bg='#134f5c', fg='#FFFFFF', command=(lambda: justprint(i)))
buttons[i].grid(row=i, column=2)
i += 1
The justprint function prints i.
def justprint(i):
print(i)
The buttons show the correct numbers. But the justprint function only prints the last number, 10, no matter which button I click.
What did I do wrong? I want to click a button and then use the number of the button as a parameter for some functions.
Answers:
You can pass i
as a default argument in the lambda function. Alternatively you can use the partial
function from functools:
from functools import partial
def bulkbuttons():
# Put all formatting related parameters of the Button constructor in a dictionary
# Using ** will pass dict values to
formatting = {'width': 12,
'borderwidth': 1,
'relief': 'raised',
'bg': '#134f5c',
'fg': '#FFFFFF'}
for i in range(10):
buttons[i]=Button(window,
text=str(i),
**formating,
command=partial(justprint,i))
buttons[i].grid(row=i, column=2)
Notes:
- Your first while loop can be expressed as this pretty and concise list comprehesion:
buttons = ['button' + str(x) for x in range(10)]
Try using this notation when possible, since they will save you typing time and is far more readable.
-
Your second while loop overwrites the list created in the first one, so there is no need to do the first while loop.
-
I took the liberty of placing all your formating related parameters for the Button constructor in a dictionary, you can pass them all at once passing **formating to the constructor. You can place these parameters in your global scope (outside functions) and define models for every type of button, saving you some time and making the code more readable.
-
If you have a fixed number of iteration is a loop, use for i in range(n)
instead of a while, it will avoid some infinite loops when you forget the i+=1
I try to create buttons in tkinter using a loop.
def bulkbuttons():
i = 0
x = 0
buttons=[]
while x < 10:
buttons.append('button' + str(x))
x+=1
while i < 10:
buttons[i]=Button(window,text=str(i), width=12,borderwidth=1, relief='raised', bg='#134f5c', fg='#FFFFFF', command=(lambda: justprint(i)))
buttons[i].grid(row=i, column=2)
i += 1
The justprint function prints i.
def justprint(i):
print(i)
The buttons show the correct numbers. But the justprint function only prints the last number, 10, no matter which button I click.
What did I do wrong? I want to click a button and then use the number of the button as a parameter for some functions.
You can pass i
as a default argument in the lambda function. Alternatively you can use the partial
function from functools:
from functools import partial
def bulkbuttons():
# Put all formatting related parameters of the Button constructor in a dictionary
# Using ** will pass dict values to
formatting = {'width': 12,
'borderwidth': 1,
'relief': 'raised',
'bg': '#134f5c',
'fg': '#FFFFFF'}
for i in range(10):
buttons[i]=Button(window,
text=str(i),
**formating,
command=partial(justprint,i))
buttons[i].grid(row=i, column=2)
Notes:
- Your first while loop can be expressed as this pretty and concise list comprehesion:
buttons = ['button' + str(x) for x in range(10)]
Try using this notation when possible, since they will save you typing time and is far more readable.
-
Your second while loop overwrites the list created in the first one, so there is no need to do the first while loop.
-
I took the liberty of placing all your formating related parameters for the Button constructor in a dictionary, you can pass them all at once passing **formating to the constructor. You can place these parameters in your global scope (outside functions) and define models for every type of button, saving you some time and making the code more readable.
-
If you have a fixed number of iteration is a loop, use
for i in range(n)
instead of a while, it will avoid some infinite loops when you forget thei+=1