Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Tkinter: Bind function to list of variables in a for-loop

I'm building an application with a lot of buttons, so I use a list of them and a for-loop to bind a function to each of them that prints the button's text when clicked. When I bind it to each button individually everything works fine, but when I use the for-loop every button only prints the text of the last item in the button list (which is "3" in this case).

import tkinter as Tk
from tkinter import *

win = Tk()

b1 = Button(win, text="1")
b1.grid(row=0)
b2 = Button(win, text="2")
b2.grid(row=0,column=1)
b3 = Button(win, text="3")
b3.grid(row=0,column=2)

button_list = [b1,b2,b3]

def printText(item):
    print(item["text"])

for button in button_list:
    button.bind("<Button-1>",lambda a:printText(button))

root.mainloop()

From what I've seen in similar questions this has something to do with lambda, however I'm not familiar with the lambda function and I'm struggling to understand how to go about fixing this.

like image 278
Natalie Avatar asked Nov 01 '25 19:11

Natalie


1 Answers

The reason of the behaviour is that all the lambdas use the same button variable, which contains the last button for the moment of pressing any button. The functions behaviour is called closure. You can pass every button in the loop by means of an argument with a default value. The approach lets us save each button in that argument, so each lambda would use its own button.

import tkinter as tk


def print_btn_text(item):
    print(item["text"])

root_win = tk.Tk()
b1 = tk.Button(root_win, text="1")
b1.grid(row=0)
b2 = tk.Button(root_win, text="2")
b2.grid(row=0, column=1)
b3 = tk.Button(root_win, text="3")
b3.grid(row=0, column=2)

button_list = [b1, b2, b3]
for button in button_list:
    button.bind("<Button-1>", lambda event, btn=button: print_btn_text(btn))

root_win.mainloop()
like image 170
I_Can_Help Avatar answered Nov 03 '25 10:11

I_Can_Help



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!