Tkinter: passing parameters to menu commands
Kent Johnson
kent3737 at yahoo.com
Sat Jan 8 11:43:43 EST 2005
Philippe C. Martin wrote:
>>>menu.add_cascade(label="File", menu=filemenu)
>>>filemenu.add_command(label="New", command=lambda: callback('New'))
>>>filemenu.add_command(label="Open...", command=lambda:
>
>>>Of course you could do this with named forwarding functions if you
>
> prefer
>
>
> I'm not sure what 'named forwarding functions'
Bad choice of terminology, I just mean you can explicitly define
def handleNew:
callback('New')
etc.
are but I'm actually in a
> class and when applying your suggestion in the following manner,
> everything works (THANKS!)
>
> ****************************
> def __Dec(self,p_string):
> for i in p_string:
> self.__Insert(i)
> .
> .
> .
> #menu creation
> l_dec.add_command(label = 'ATR', command=lambda: self.__Dec('ATR'))
> l_dec.add_command(label = 'IN', command=lambda:self.__Dec('IN'))
> .
> .
> .
> ****************************
>
> Yet I have a question:
>
> If I replace the menu creation code as below, and since __Insert appends
> the string p_string into a text widget that is created _after_ the menu
> creation; the method __Dec seems to be called at the menu creation and
> I get an error in __Insert because the test widget is equal to None.
>
> My reflexes of C programmer tell me that command=self.__Dec.... just
> passes a method pointer (sorry I said it) to add_command - yet it does
> not seem to be so.
>
> What is actually going on ?
>
>
> #menu creation
> l_dec.add_command(label = 'ATR', command=self.__Dec('ATR'))
> l_dec.add_command(label = 'IN', command=self.__Dec('IN'))
self.__Dec is a reference to the function. It is similar to a method pointer so you don't need to
apologize ;) The name of a function without the () is a reference. When you append () it becomes a
call to the referenced function.
The command parameter for the menu must be a reference to a function. The function is called with no
arguments when the menu is invoked.
So, you need a function of no arguments to handle the command. For example,
def handleMenu():
print 'Handled'
filemenu.add_command(label="New", command=handleMenu)
Note there is no () after handleMenu. 'command' is bound to the function object; the function is not
called until later.
OK, now suppose you want to pass a parameter to handleMenu?
def handleMenu(menuName):
print 'Handled', menuName
Now what do you put in the command parameter? This won't work because you are *calling* handleMenu
and assigning the result of the call (in this case the value None) to 'command':
filemenu.add_command(label="New", command=handleMenu('New')) # WRONG
You need a new function of zero arguments to bind to 'command'. Here is one way to do it:
def handleNew():
handleMenu('New')
filemenu.add_command(label="New", command=handleNew) # OK
Note, again, no () after handleNew. 'command' is bound to the function object again.
OK, what about lambda? lambda is a way to create a simple anonymous function. One simple use of
lambda is to make a new function that binds a parameter to another function.
lambda: handleMenu('New')
defines a function that does the same thing as handleNew. The value of the lambda expression is the
function object. So
filemenu.add_command(label="New", command=lambda: handleMenu('New')) # OK
is another way to get the result you want.
Kent
More information about the Python-list
mailing list