Calling a sequence of commands with a sequence of Tkinter buttons

Steve Purcell stephen_purcell at yahoo.com
Tue Feb 20 08:10:59 EST 2001


Martyn Quick wrote:
> MY ATTEMPT:
> 
> from Tkinter import *
> 
> ...
> 
> for i in range(20):
> 	buttons.append(Button(root,text="Button "+`i`,command=f(i)))
> 	buttons[i].pack()
> 	# This doesn't work - it just prints 1,2,..,20 down the screen
> 	# immediately, since f(i) is called at the creation of the button.

Right, you found the problem; f() is called immediately. Instead, give
Tkinter a new function that takes no parameters and that can be called later:

	for i in range(20):
	  def f_i(j=i):
	    f(j)
	  buttons.append(Button(root,text="Button "+`i`,command=f_i))
	  buttons[i].pack()


Of, if you prefer:

	for i in range(20):
	  buttons.append(Button(root,text="Button "+`i`,
				command=lambda j=i, f(j)))
	  buttons[i].pack()


It would perhaps be neater to solve this with a callable class instance than
with a default function argument:

	class PrintNumberAction:
	   def __init__(self, i):
	      self.i = i
	   def __call__(self):
	      print i  # or whatever

then:

	for i in range(20):
	   action = PrintNumberAction(i)
	   buttons.append(Button(root,text="Button "+`i`,command=action))
	   buttons[i].pack()

Hope that helps.

-Steve

-- 
Steve Purcell, Pythangelist
Get testing at http://pyunit.sourceforge.net/
Get servlets at http://pyserv.sourceforge.net/
"Even snakes are afraid of snakes." -- Steven Wright




More information about the Python-list mailing list