[Tkinter-discuss] command for dynamic buttons

Guilherme Polo ggpolo at gmail.com
Sat Aug 8 00:06:54 CEST 2009


2009/8/7 boivie <boivie at hotmail.com>:
> Hello! I'm making an application with lots of similar buttons. But I can't
> figure out how to make the command unique for each button. I tried to follow
> the advice in this old message, but every button still gives the same
> output.
>
> class Program:
>     def __init__(self, ruta):
>
>         bokst = ['а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к']
>
>         i = 1
>         for option in bokst:
>             laddaKnapp = lambda index=0, obj=self: obj.tryck(option)
>             knapp = Button(self.nere, text=str(option), command=laddaKnapp)
>             knapp.grid(row=1, column=i)
>             i = i + 1
>
>     def tryck(self, bokstav):
>         self.currText.set(bokstav)
>         return
>
> I found how to do it in pygtk in this example, but I've not been able to
> find a singel example of dynamic buttons in tkinter.

Actually this is not tkinter fault, and pygtk doesn't do magic here either.

For instance, if you translated this to pygtk you would get this:

import gtk

def test(option):
    print option

things = ['a', 'b', 'c', 'd']

win = gtk.Window()
hbox = gtk.HBox()
win.add(hbox)

for indx, option in enumerate(things):
    cmd = lambda event: test(option)
    btn = gtk.Button(option)
    btn.connect('clicked', cmd)
    hbox.pack_start(btn)

win.show_all()
win.connect('destroy', gtk.main_quit)
gtk.main()

Which would always print 'd'. Of course you could change that
"connect" to: btn.connect('clicked', test, option) which you would
proceed to change the test callback to accept an event parameter as
the first argument, but this code is really different.

I didn't look at the email you pointed, but if the suggestion included
there maps to the code you posted then the suggestion is wrong.

import Tkinter

def test(option):
    print option

things = ['a', 'b', 'c', 'd']

root = Tkinter.Tk()

for indx, option in enumerate(things):
    cmd = lambda opt=option: test(opt)
    btn = Tkinter.Button(text=option, command=cmd)
    btn.pack(side='left')

root.mainloop()

The line you are after is "cmd = lambda opt=option: test(opt)". If
instead you do "cmd = lambda: test(option)" (which is equivalent to
what the code you pasted was doing), then when this lambda executes it
will have to grab the value of this name "option" from somewhere,
which will be the last element from the things list.


-- 
-- Guilherme H. Polo Goncalves


More information about the Tkinter-discuss mailing list