Robin Andrews
Robin Andrews

Reputation: 3794

Tkinter Button Callback Lambda Unexpected Result

I want to create multiple rows of tkinter widgets and I thought storing them in a dictionary would be a clean way to do this. I'm having trouble getting the callbacks for the buttons to work correctly though. With the code as is, the value passed to the button callback is always E and I can't see why that is. How do I pass the correct key to the callback please - i.e. A for the first row, B for the second etc?

import tkinter as tk

NUM_ROWS = 5
BOLD_FONT = ("calbri", 16, "bold")
NORMAL_FONT = ("calbri", 16, "normal")


def submit():
    print("you win")


def clear(key):
    print(key)
    # widgets[key]["factor_field"].delete(0,"end")
    # widgets[key]["factor_field"].insert(0, key)


data = {}
widgets = {}

root = tk.Tk()

# Build widgets
for i in range(NUM_ROWS):
    key = chr(i + 65)
    this_row = widgets[key] = {}
    this_row["label"] = tk.Label(root, text=key, font=BOLD_FONT)
    this_row["label"].grid(row=i, column=0, padx=5, pady=10)
    this_row["factor_field"] = tk.Entry(root, width=60, font=NORMAL_FONT)
    this_row["factor_field"] .grid(row=i, column=1, padx=5, pady=10)
    this_row["target_node_field"] = tk.Entry(root, width=5, font=NORMAL_FONT)
    this_row["target_node_field"].grid(row=i, column=2, padx=5, pady=10)
    this_row["clear_button"] = tk.Button(root, text="Clear", command=lambda: clear(
        key), font=BOLD_FONT).grid(row=i, column=3, padx=5, pady=10)

submit_button = tk.Button(root, text="Submit", command=submit,
                          font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=0, padx=5, pady=10)

print(widgets)
root.mainloop()

Upvotes: 0

Views: 59

Answers (1)

Ji Wei
Ji Wei

Reputation: 881

Use this:

this_row["clear_button"] = tk.Button(root, text="Clear", 
                                     command=lambda x=key: clear(x), 
                                     font=BOLD_FONT)
this_row["clear_button"].grid(row=i, column=3, padx=5, pady=10)

In your current code, the value for the key variable is fixed at E after the for loop has completed. As a result, your existing lambda function will always call clear('E').

Upvotes: 1

Related Questions