Updated 2011-11-20 06:16:58 by RLE

Richard Suchenwirth 2006-08-24 - Specifying menu items can get a bit verbose due to several keywords that have to be used, but since TkPhotoLab I've started to use this little wrapper which concentrates the ugly reality in one place, and henceforth allows me to use beautifully simple menu specifications:
 proc m+ {head name {cmd ""}} { 
    if {![winfo exists .m.m$head]} { 
         .m add cascade -label $head -menu [menu .m.m$head -tearoff 0] 
    if [regexp ^-+$ $name] { 
            .m.m$head add separator 
    } elseif {[regexp {^\?(.+)} $name -> name]} {
        .m.m$head add checkbutton -label $name -variable $cmd
    } else {.m.m$head add command -label $name -comm $cmd} 
#-- Demo example: 
 pack [text .t]
 . configure -menu [menu .m] 
 m+ File Open {.t insert end "opened\n"} 
 m+ File Save {.t insert end "saved\n"} 
 m+ File ----- 
 m+ File Exit exit 

 m+ Edit Cut ... 
 m+ ?Verbose verbose ;# checkbutton, toggles the global variable "verbose"

 pack [text .t -wrap word] -fill both -expand 1

An earlier, less simple approach is at Menus made easy

DKF: Here's a version that does a little bit more processing:
 proc m+ {head name {cmd ""}} { 
    # OK, it's using an undocumented and unsupported feature of Tk; it's convenient though
    if {![winfo exists .m.m$head]} { 
       foreach {l u} [::tk::UnderlineAmpersand $head] break
       .m add cascade -label $l -underline $u -menu [menu .m.m$head -tearoff 0] 
    if {[regexp ^-+$ $name]} { 
       .m.m$head add separator 
    } else {
       foreach {l u} [::tk::UnderlineAmpersand $name] break
       .m.m$head add command -label $l -underline $u -comm $cmd

I've done even more complex versions in the past where I'd also give the binding for the hotkey for the menu entry and the code would generate the accelerator to go with that as well as binding the accelerator correctly. It's nice, but the code is (very) long-winded.

Here's how I'd write the above example with this new version:
 pack [text .t]
 . configure -menu [menu .m] 
 m+ &File &Open {.t insert end "opened\n"} 
 m+ &File &Save {.t insert end "saved\n"} 
 m+ &File ----- 
 m+ &File E&xit exit 

 m+ &Edit &Cut ... 

Bryan Oakley I've never liked the overly complex menu systems like Menus made easy but I also don't like spelling them out longhand. The above m+ approach is great. In the past I've done something similar, though I allow one to specify all the menu options and use a slightly different syntax that allows for arbitrarily deep menus (though I rarely go beyond two, and never beyond three):
  mm &View->&Fonts->&Choose... -command {...}

Alas, at the moment I don't have the code handy, but it's pretty darn easy to recreate.

HJG What unsupported Tk-feature is used here ?

ZB It seems, he meant ::tk::UnderlineAmpersand. Very nice and handy solution, indeed...