[Tkinter-discuss] Tip: how to enable/disable menu items

stewart at midtoad.homelinux.org stewart at midtoad.homelinux.org
Tue Sep 28 23:11:32 CEST 2004


I need to be able to enable or disable menus in a Tkinter app that uses a Pmw
menubar.  I easily found a sample app (first sample below) that shows how to
disable a Tkinter menubar, but I'm using the Pmw widget set, so this sample
won't work as listed.  So I went looking for clues, and it took quite a while to
find them!  Eventually I found something, and with some experimentation, got it
to work. My sample app is attached (second sample below).  

The trick is to reference menu entries by an index number (0 for the first
entry, 1 for the second, etc.).  You can also enable or disable cascading menus
this way (though I haven't tried disabling individual entries in a cascaded
menu).  The non-obvious part is that if you want to disable, say, the 'Options'
menu, you have to enter 'Options-menu' in the following line:
self.menuBar.component('Options-menu').entryconfig(0,state='disabled')

Hope this helps someone!

cheers
Stewart

#--- sample 1: Disabling Tkinter menu items --------

from Tkinter import *

root=Tk()

def hello():
    print "hello !"

def toggle():
    if submenu.entrycget(0,"state")=="normal":
        submenu.entryconfig(0,state=DISABLED)
        submenu.entryconfig(1,label="Speak please")
    else:
        submenu.entryconfig(0,state=NORMAL)
        submenu.entryconfig(1,label="Quiet please")

menubar = Menu(root)

submenu=Menu(menubar,tearoff=0)

submenu2=Menu(submenu,tearoff=0)
submenu2.add_command(label="Hello", command=hello)

# this cascade will have index 0 in submenu
submenu.add_cascade(label="Say",menu=submenu2,state=DISABLED)
# these commands will have index 1 and 2
submenu.add_command(label="Speak please",command=toggle)
submenu.add_command(label="Exit", command=root.quit)

menubar.add_cascade(label="Test",menu=submenu)

# display the menu
root.config(menu=menubar)
root.mainloop()

# -------- Sample Two: Disabling Pmw menuBar items ------------
title = 'Disable menuBar items demonstration'

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

import Tkinter
import tkFont
import tkMessageBox
import Pmw

class Demo:
    def __init__(self, parent):
        self.font = ('Helvetica', 10, 'normal')
        
        # 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')

        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: self.setFont(ss),
                                font=self.font,
                                label = size)
    
        menuBar.addmenuitem('Options', 'command', 'Change font size',
            command = lambda: self.chgFont(),
            font=self.font,
            label = 'Change size')

        menuBar.addmenuitem('Options', 'command', 'Enable/disable the menu',
            command = self.toggle,
            font=self.font,
            label = 'Disable Size menu')

        # 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 toggle(self):
        '''disable the first Options menu item, or enable it if already disabled.
           item 0 is the first menu item, item 1 is the second, etc.
           Note that to disable an item in the Options menu, you have to enter
           "Options-menu" below. Similarly, for an item in File menu, enter
File-menu'''
        if self.menuBar.component('Options-menu').entrycget(0,"state")=="normal":
            self.menuBar.component('Options-menu').entryconfig(0,state='disabled')
            self.menuBar.component('Options-menu').entryconfig(2,label="Enable
Size menu")
        else:
            self.menuBar.component('Options-menu').entryconfig(0,state='normal')
            self.menuBar.component('Options-menu').entryconfig(2,label="Disable
Size menu")

    def setFont(self, size):
        print 'current font: ',self.font
        #('tiny', 'small', 'average', 'big', 'huge')
        
        newFont = {'tiny': ('Helvetica', 6, 'normal'), 
                    'small': ('Helvetica', 8, 'normal'), 
                    'average': ('Helvetica', 10, 'normal'), 
                    'big': ('Helvetica', 12, 'normal'),
                    'huge': ('Helvetica', 14, 'normal'),
                    'monstrous': ('Helvetica', 18, 'normal')}
        self.font = newFont[size]
        print 'new font size: ', size, ' ', str(self.font)
        
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