Title: Wanna handle click event on buttons made using loop
Tags: python;tkinter;tkinter-button
Question: I used for loop to create buttons in tkinter. And wanna apply an event on all the created button. Event is like, when I click on button its bg color should change and won't back to normal until I click back on it. But in my code color of last button is changing only.
def button_Clicked(e):
bij['bg'] = 'red'
for i in range (0,8):
for j in range (0,8):
bij = tk.Button(compFrame, width = 10, height=4)
bij.grid(row = i, column = j, padx = 5, pady = 5)
bij.bind(&quot;<Button-1&gt;&quot;, button_Clicked)
Is there any way that I can connect all the buttons with event that if I clicked on any button then only its color should change not of the last one or any others.
Comment: that was my mistake, bind command was inside the loop

Comment: Is this really how your code is indented? You're only calling `bind` on the last button that was created.

Comment: Then please update the code in your question.


Here is another answer: Updated Answer:
As @Thingamabobs pointed out, it's possible to get the button via e.widget in button_Clicked function via the event object e. Thus, it's not necessary to pass the button object to the function.
def button_Clicked(e):
button = e.widget
# toggle between 'red' and default color
if button['bg'] != 'red':
button['bg'] = 'red'
else:
button['bg'] = 'SystemButtonFace'
for i in range(0, 8):
for j in range(0, 8):
bij = tk.Button(compFrame, width=10, height=4)
bij.grid(row=i, column=j, padx=5, pady=5)
bij.bind(&quot;<Button-1&gt;&quot;, button_Clicked)
root.mainloop()
Old Answer:
You need to bind the event inside the loop. Right now, bij is outside the loop, so it's only the last button.
To make sure the event changes color for the correct button, you need to add an argument to button_Clicked
To change toggle the background color on each click, it's necessary to add a condition in button_Clicked
def button_Clicked(e, button):
# toggle between 'red' and default color
if button['bg'] != 'red':
button['bg'] = 'red'
else:
button['bg'] = 'SystemButtonFace'
for i in range (0,8):
for j in range (0,8):
bij = tk.Button(compFrame, width = 10, height=4)
bij.grid(row = i, column = j, padx = 5, pady = 5)
bij.bind(&quot;<Button-1&gt;&quot;, lambda event, bij=bij: button_Clicked(event, bij))
As @BryanOakley rightly point out, it's necessary to use the trick
lambda event, bij=bij: button_Clicked(event, bij)
to make sure the lambda closure uses the current bij value in the loop.
Alternatively, it's possibly cleaner to use functools.partial for the last line
from functools import partial
bij.bind(&quot;<Button-1&gt;&quot;, partial(button_Clicked, button=bij))
Comment for this answer: But still it is not working. only changing color of last button.
Comment for this answer: Thank you so much sir. I got it now.
Comment for this answer: You're making a very common mistake. See https://stackoverflow.com/questions/10865116/
Comment for this answer: @MDDANISH if someone took the time to help you out, it is good practice to *reward* them by [accept](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) their answers. We feel valued helping you gain progress. All of your questions have no accepted answers. You may reread those answers too.
Comment for this answer: @Tim parsing the button through is kind of redundant, since you could just do `e.widget` to get the button.
Comment for this answer: @BryanOakley well caught, answer updated. It's tested and working now.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 3, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2022:00:08/31/22', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<python><tkinter><tkinter-button>', 'Title': 'Wanna handle click event on buttons made using loop', 'ViewCount': 32, 'id': 73558893, 'user_AboutMe': None, 'user_AccountId': 23656403.0, 'user_DisplayName': 'MD DANISH', 'user_Reputation': 1.0, 'user_Views': 6.0, 'user_id': 17684626.0}}