0

I have tkinter_sandbox.py:

from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Tkinter bug?")
mainframe = ttk.Frame(root)
mainframe.grid(column=0, row=0)
buttons = []

for i in range(3):
    buttons.append(ttk.Button(mainframe, text="1", command=lambda:print(i)))
    buttons[i].grid(row=1, column=i+1)

root.mainloop()

Then, I execute the code using python tkinter_sandbox.py on cmd. A window pops up, and I click on the buttons from left to right once.

The output on the console is 2 2 2, whereas 0 1 2 is expected.

Specs:

  • Python 3.5.1
  • Tkinter version 8.6
  • Windows 7 Enterprise
Kenny Lau
  • 457
  • 5
  • 13
  • I find the downvote and duplication mark unreasonably dismissive. The OP may not realize that the lambda function inside the loop is the cause of the problem. (In fact, I think he suspected that it was a bug in Tkinter.) IMHO it is more appropriate with an answer pointing out the problem with the lambda. – sigvaldm Oct 16 '18 at 12:05

2 Answers2

3

the problem is that you need to pass the arguments through the lamba declaration:

command=lambda:print(i)

needs to be:

command=lambda i=i:print(i)

so complete code:

from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Tkinter bug?")
mainframe = ttk.Frame(root)
mainframe.grid(column=0, row=0)
buttons = []

for i in range(3):
    buttons.append(ttk.Button(mainframe, text="1", command=lambda i=i:print(i)))
    buttons[i].grid(row=1, column=i+1)

root.mainloop()
James Kent
  • 5,763
  • 26
  • 50
2

You're using i to create the buttons and it's being updated to a new value by the command is taking place.

Fixed code:

from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Tkinter bug?")
mainframe = ttk.Frame(root)
mainframe.grid(column=0, row=0)
buttons = []

for i in range(3):
    buttons.append(ttk.Button(mainframe, text="1", command=lambda x=i:print(x)))
    buttons[i].grid(row=1, column=i+1)

root.mainloop()
muddyfish
  • 3,530
  • 30
  • 37