Sounds like all your widgets are sharing an event handler. This excerpt from the Tkinter 8.5 Reference by John W. Shipman - NM Tech, may help.
54.7. The extra arguments trick
Sometimes you would like to pass other
arguments to a handler besides the
event.
Here is an example. Suppose your
application has an array of ten
checkbuttons whose widgets are stored
in a list self.cbList
, indexed by
the checkbutton number in range(10)
.
Suppose further that you want to write
one handler named .__cbHandler
for
<Button-1>
events in all ten of
these checkbuttons. The handler can
get the actual Checkbutton
widget
that triggered it by referring to the
.widget
attribute of the Event
object that gets passed in, but how
does it find out that checkbutton's
index in self.cbList
?
It would be nice to write our handler
with an extra argument for the
checkbutton number, something like
this:
def __cbHandler(self, event, cbNumber):
But event handlers are passed only one
argument, the event. So we can't use
the function above because of a
mismatch in the number of arguments.
Fortunately, Python's ability to
provide default values for function
arguments gives us a way out. Have a
look at this code:
def __createWidgets(self):
...
self.cbList = [] # Create the checkbutton list
for i in range(10):
cb = Checkbutton(self, ...)
self.cbList.append(cb)
cb.grid(row=1, column=i)
def handler(event, self=self, i=i): # [1]
return self.__cbHandler(event, i)
cb.bind("<Button-1>", handler)
...
def __cbHandler(self, event, cbNumber):
...
[1]
These lines define a new function
handler
that expects three
arguments. The first argument is the
Event
object passed to all event
handlers, and the second and third
arguments will be set to their default
values?the extra arguments we need to
pass it.
This technique can be extended to
supply any number of additional
arguments to handlers.
A slightly more concise way to do this, as @Bryan Oakley does for the second button in his answer, is to define each handler function in-line with a lambda
expression, i.e.:
def __createWidgets(self):
...
self.cbList = [] # Create the checkbutton list
for i in range(10):
cb = Checkbutton(self, ...)
self.cbList.append(cb)
cb.grid(row=1, column=i)
cb.bind("<Button-1>", lambda event, self=self, i=i:
self.__cbHandler(event, i))
...
def __cbHandler(self, event, cbNumber):
...