0

I face an issue which is that my first button is using the second button's command. I have faced this logic error multiple times when trying to create buttons programmatically with different functions, is there a way to resolve this or is this a limitation to Tkinter? The gif below illustrates my issue.

import tkinter as tk
root = tk.Tk()
root.geometry("400x400")

def print_when_clicked(message):
    print(message)

array = ["hi", "bye"]

for i in array:
    tk.Button(root, text=i, command=lambda:print_when_clicked(i)).pack()

enter image description here

1 Answers1

1

You have fallen in to one of the classic Python traps. The issue is that the lambda captures the i variable, NOT the value of i. So, after the loop finishes, i is bound to "bye", and both functions use it.

The trick to work around this is to use a fake default argument:

for i in array:
    tk.Button(root, text=i, command=lambda i=i:print_when_clicked(i)).pack()
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • Hello, I was wondering if making the lambda function a separate variable something like `l = lambda i: print_when_clicked(i)` and then using it like ``` for i in array: tk.Button(root, text=i, command=l(i)).pack() ``` could be a good workaround? – IStackoverflowAndIKnowThings Feb 08 '22 at 04:13
  • Nope, that will call the lambda inside the loop, which is not what you want. That's exactly like `def l(i):` / `print_when_clicked(i)`. – Tim Roberts Feb 08 '22 at 07:08