[Tkinter-discuss] passing parameters to a lambda function in Tkinter menubar

stewart at midtoad.homelinux.org stewart at midtoad.homelinux.org
Sat Sep 25 02:26:07 CEST 2004



Here's a problem I keep running into. It occurs when I try to pass parameters to
a menubar item's command property using a lambda function. Probably it's a
scoping problem, but I don't see how to resolve it (except not to pass parameters). 

Essentially the problem is this: if you simply call a method as the command
callback when you are creating a GUI, that command will be executed right away
when the GUI is drawn - at least, if you pass that method any arguments.  

One way to get around this is not pass arguments to the callback methods.  I
thought another way might be to use a lambda function, and pass it the
arguments. That works if the lambda calls another class, but if it calls a
method in the same class, I get name errors. 

In the attached mini-app, which uses Pmw, the File > Close menu selection uses a
lambda function that passes a parameter to another class with a __call__ method.
It works properly.

However, the Options > Set size To menu choice, which uses a lambda function to
pass the size string to a setFont method, does not work.  It looks as though the
lambda function doesn't know it's part of the Demo class, so it can't find the
self.setFont method.  If I replace 'self' with the name of the class, Demo, I
instead get an error saying 'unbound method must be called with class instance
1st argument'.

Can anyone shed any light on how make this latter method work? It would greatly
clean up my app.

thanks
Stewart
  
-------------- next part --------------
title = 'FontSize demonstration'

# Import Pmw from this directory tree.
import sys
sys.path[:0] = ['c:\\programs']

import Tkinter
import tkFont
import Pmw

class Demo:
    def __init__(self, parent):

        self.font = ('Helvetica', 10)           
        # Create and pack the MenuBar.
        menuBar = Pmw.MenuBar(parent,
            hull_relief = 'raised',
            hull_borderwidth = 1)
        menuBar.pack(fill = 'x')
        self.menuBar = menuBar

        # Add some buttons to the MenuBar.
        menuBar.addmenu('File', 'Close this window or exit', font=self.font)
        menuBar.addmenuitem('File', 'command', 'Close this window',
            command = PrintOne('Action: close'),
            font=self.font,
            label = 'Close')
        menuBar.addmenuitem('File', 'separator')
        menuBar.addmenuitem('File', 'command', 'Exit the application',
            command = lambda: sys.exit("Bye"),
            font=self.font,
            label = 'Exit')

        #  command = PrintOne('Action: exit'),

        menuBar.addmenu('Options', 'Set user preferences', font=self.font)
        menuBar.addcascademenu('Options', 'Size',
            'Set some other preferences', traverseSpec = 'z', tearoff = 1, font=self.font)
        for size in ('tiny', 'small', 'average', 'big', 'huge', 'monstrous'):
            menuBar.addmenuitem('Size', 'command', 'Set size to ' + size,
                                command = lambda ss=size: Demo.setFont(ss),
                                font=self.font,
                                label = size)


        # Create and pack the main part of the window.
        self.mainPart = Tkinter.Label(parent,
            text = 'This is the\nmain part of\nthe window',
            font=self.font,
            background = 'white',
            foreground = 'black',
            padx = 30,
            pady = 30)
        self.mainPart.pack(fill = 'both', expand = 1)

    def setFont(self, size):
        print 'current font: ',self.font
        #('tiny', 'small', 'average', 'big', 'huge')
        print 'new font: ', size
        

class PrintOne:
    def __init__(self, text):
        self.text = text

    def __call__(self):
        print self.text



######################################################################

# Create demo in root window for testing.
if __name__ == '__main__':
    root = Tkinter.Tk()
    Pmw.initialise(root)
    root.title(title)

    exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy)
    exitButton.pack(side = 'bottom')
    widget = Demo(root)
    root.mainloop()


More information about the Tkinter-discuss mailing list