menubar(3tk)
π menubar β the menubar(3tk) page, bestie edition β¨
okay so this is the manual for menubar from the Tcl/Tk world β it's the menubar(3tk) page, and it's long, so we're doing this in four parts. grab a snack π. this is part 1.
β¨ NAME β¨
menubar β Creates an instance of the menubar Class.
like. it makes a menubar object. that's the whole vibe.
πΈ SYNOPSIS πΈ
package require Tcl 8.6
package require Tk 8.6
package require menubar ?0.5.1?
menubar new ?options?
mBarInst define body
mBarInst install pathName body
mBarInst menu.configure option tag-settings ?option tag-settings ...?
mBarInst menu.namespace tag namespace
mBarInst menu.hide tag
mBarInst menu.show tag
mBarInst tag.add tag value
mBarInst tag.configure pathName tag ?option value ...option value?
mBarInst tag.cget pathName tag ?option?
mBarInst group.add tag label ?cmd? ?accel? ?sequence? ?state?
mBarInst group.delete tag label
mBarInst group.move direction tag label
mBarInst group.configure tag label ?option value ...option value?
mBarInst group.serialize tag
mBarInst group.deserialize tag stream
mBarInst notebook.addTabStore pathname
mBarInst notebook.deleteTabStore pathname
mBarInst notebook.setTabValue pathname tag
mBarInst notebook.restoreTabValues pathname
π¦ DESCRIPTION π¦
menubar new ?options?
so this one makes a brand new instance of the menubar class and hands it back to you, no cap. the menubar class is literally the whole package: it handles defining, installing, and all the dynamic behavior of a menubar. π
the cute part? it does not depend on any widget framework, so you can use it with or without one (think Bwidget, IWidget, Snit, etc. β she's flexible like that). π
and here's the thing that trips people up: unlike basically every other Tk widget command, the menubar command has no pathName argument. why? because menubars aren't handled by the application β they're handled by the window manager (aka wm). she's not like other widgets, periodt. π
π OPTIONS π
these are the options you can pass to the menubar new command. π«Ά
heads up bestie β these are inherited from the Tk menu command, which means their effect is platform specific. so what slays on one OS might not hit the same on another. π
-activebackgroundβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-activebackground]-activeborderwidthβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-activeborderwidth]-activeforegroundβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-activeforeground]-backgroundβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-background]-borderwidthβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-borderwidth]-cursorβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-cursor]-disabledforegroundβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-disabledforeground]-fontβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-font]-foregroundβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-foreground]-reliefβ [http://docs.activestate.com/activetcl/8.5/tcl/TkCmd/options.htm#M-relief]
π INTRODUCTION π
an instance of the menubar class gives you methods for compiling a description of the menubar, configuring menu items, and installing the menubar into toplevel windows. three jobs. she does all three. π
think of a menubar as a tree of cascading menus. π³ you define a menubar using a language that produces a human readable description of a menubar. then an instance of the menubar class compiles that description, and after that you can install it into one or more toplevel windows. so write once, install everywhere β that's the energy. β¨
and the menubar class has a bunch of unique capabilities that you just won't find in other tcl/tk menubar implementations. some of them are:
- a tagging system that simplifies access to menu entries in the menu tree. π·οΈ
- support for user defined tags that depend on the toplevel window context.
- a simplified and uniform interface for all callback commands.
- namespace support for all callback commands, so callback commands can be easily grouped into namespaces.
- support for hiding and exposing menus on the menubar. π
- a simplified method for creating radiobutton groups.
- automatic management of state variables for checkbuttons and radiobuttons.
- scope control for the state variables of checkbuttons and radiobuttons.
- tear-off menu management that ensures only one tearoff menu is created.
- support for dynamic menu extension to simplify the creation of recent document menus.
- support for saving and restoring dynamic menu extensions.
like?? she's doing the most and we love her for it. π₯
π§ TERMINOLOGY π§
okay bestie, vocab check. these words come up constantly so lock in. π
MENUBAR
the visible rendering of a menubar in a toplevel window is a horizontally group of cascading Tk menus. (yes, that's the original wording, we keep it fr fr.) so: horizontal row of menus, at the top, that's your menubar. π
MENU
a menu is an ordered list of items that is rendered vertically. menus are not visible until a user performs some action (normally a <ButtonPress-1> event β yes, a click π). a menu may contain any number of child menus, which get rendered as cascading menus. those cascading menus are rendered next to the parent menu when they are activated. β¨
MENU ENTRY
a menu contains an ordered list of items called entries. menu entries have a type, and the menubar class supports the following 6 entry types: Command, Checkbutton, Radiobutton, Separator, Group and Menu. six. that's the whole roster. π
ENTRY LABEL
each menu entry has a visible string, and that string is called the entry label. that's it. that's the term. π
TAG
a tag is a name that's normally used to refer to an item in a menu tree. a tag name is an alphanumeric character string that may include the underscore character. menu tree tags are defined for all nodes and leafs in a menu tree. this gives you a flat abstraction of the tree, which simplifies item referencing in menubar methods. π·οΈ
and why do you want that abstraction? because otherwise you'd have to reference menu elements using a tree path, and a tree path could change at run-time. no thank you. π
the menubar class also has a method that can create a user defined tag. user defined tags store values that change based on the currently active toplevel window. so you can use them to store widget pathnames used by callback code, and that way your output gets routed to the appropriate toplevel window. main character routing energy. π
part 1 done bestie, more coming β don't go anywhere π
π οΈ METHODS π οΈ
mBarInst define body
Bestie, this is where you build the whole look of your menubar. It compiles body into a tree of menu entries which define the visual layout of the menubar. The body argument describes the layout using the following syntax, and all the elements of that syntax get explained right below, i promise π
body == definitions
definitions ::= { <ignore> | <definition> | <definition> <definitions> }
ignore ::= { <nl> | <white-space> <nl> | # <comment> <nl> }
definition ::= { <command> | <checkbutton> | <radiobutton> | <separator> | <group> | <menu> }
command ::= <label> C <tag> <nl>
checkbutton ::= <label> X<scope> { <tag> | <tag>+ } <nl>
radiobutton ::= <label> R<scope> { <tag> | <tag>+ } <nl>
separator ::= <stext> S <tag> <nl>
group ::= <dummy> G <tag> <nl>
menu ::= <label> { M:<tag> | M:<tag>+ } <nl> <definitions>
stext ::= '--' | <label>
scope ::= '' | '@' | '='
C - Command β¨
The C type entry is the most common type of entry. This entry executes a command when it is invoked. That's it, that's the whole vibe β you click, it runs. π
X - Checkbutton βοΈ
A X type entry behaves much like a Tk checkbutton widget. When it is invoked it toggles back and forth between a selected and deselected states. The value of a checkbutton is a boolean (i.e. 1 or 0). By default all checkbuttons are deselected. If you want the checkbutton to be initially selected then include a trailing plus (+) with the tag name. See SCOPE CONTROL below for a description of the scope indicator.
R - Radiobutton π
A R type menu entry behaves much like a Tk radiobutton widget. Each radiobutton entry is a member of a radiobutton group that controls the behavior of the radiobuttons in the group. All radiobuttons in a group are given the same tag name. In the example below Red, Green and Blue all have the same tag and are therefore all in the same radiobutton group. A trailing plus (+) on the tag name of a radiobutton entry will cause the entry to be the initially selected entry. See SCOPE CONTROL below for a description of the scope indicator.
S - Separator β
A S type menu entry is an entry that is displayed either as a horizontal dividing line or a label. Separators are not active elements of a menu and have no associated behavior if they are invoked. Like, they're decorative, they don't do anything, don't come for them. If <stext> is two dashes (i.e. '--') then the separator will be displayed as a horizontal line otherwise <stext> will be displayed as a bold label surrounded by double dashes (e.g. "-- <stext> --") with a lightgray background.
G - Command Group π
The G type menu entry marks a location in the menu tree where entries can be dynamically added and removed. Menu extension can only occur at the end of a menu so G type entries must be the last item on a menu. A G type entry is rendered as a separator line. The group.<xxx> sub-commands are used to manipulate command group entries.
M - Menu π
An M type entry is used to define both menubar menus and cascading menus. Menu entries are the most complicated of the 6 menu types. A menu entry is composed of three list elements. The first element of the list is its label. The second element of the list is a composite string consisting of a type identifier (M) followed by an optional tag (beginning with a ':' separator) and finally an optional plus (+) which indicates that the menu is a tear-off menu. The final element of the list is a LIST VALUE.
mBarInst install pathName body
The install method installs the menubar created with the define method into toplevel window pathName. The body argument of the command contains a tcl script which is used to initialize the installed menubar. Normally the tcl script will contain calls to various menubar methods to perform the initialization. The initialization code is only run once when the menubar is installed. The namespace in which the install method is executed becomes the default namespace for callback commands (see menu.namespace below for more details). π«Ά
π METHODS - MENU.XXX π
mBarInst menu.configure option tag-settings ?option tag-settings ...?
Configures the tags of a menubar and returns an empty string. This method provides a convenient way to configure a larger number of tags without the verbosity of using the tag.configure method. Group chat energy: say it all at once instead of one message at a time, slay.
optionβ Option may have any of the values accepted by thetag.configuremethod.tag-settingsβ The tag-settings argument is a string that is converted to a list of tag-value pairs using the following syntax.
Syntax for tag-settings.
tag-settings ::= { <ignore> | <value> | <value> <tag-settings> }
ignore ::= { <nl> | <white-space> <nl> | # <comment> <nl> }
value ::= <tag> <option-value> <nl>
mBarInst menu.namespace tag namespace
Change the namespace for a sub-tree of the menubar starting at entry tag. The new value will be namespace. Each entry in the menubar tree has an associated namespace which will be used for its callback procedure. The default namespace is the namespace where the install method was executed. The namespace method can be used to change the namespace that will be used for callbacks in a sub-tree of the menubar. This method can only be used in the context of an install script. π§
mBarInst menu.hide tag
Remove (hide) a menubar entry. When a menubar tree is defined all entries are visible by default. This method can be used to hide a menubar entry. The hide methods can be used in the context of an install script so that a menu will be initially hidden at application start up. The tag argument is the tag name of the menu to be hidden. π
mBarInst menu.show tag
Exposes (shows) a hidden menubar entry. When a menubar tree is defined all entries are visible by default. If a entry is hidden from the user (using the menu.hide method) then it can be exposed again using the show method. The tag argument is the tag name of the menu to be shown. β¨
π·οΈ METHODS - TAG.XXX β¨
mBarInst tag.add tag value
Okay so this one adds a user defined tag value β it literally adds a new tag-value pair to the tags your menubar already has. π
Heads up though: user defined tags are not the same as the tags you get from the define method, so don't go confusing the two bestie.
Also, tag.add can only be used in an install script, and its value is associated with the toplevel where the menubar is installed. Why does that matter? Because it makes the tag context sensitive β so callback code that queries the tag value will receive a value that's associated with the window that performed the callback. Iconic behavior, honestly. π
mBarInst tag.configure pathName tag ?option value ...option value?
You hand it the pathName of a toplevel window plus a tag, and it configures the menu entry associated with that tag and returns an empty string. That's it, that's the whole vibe. π
Standard Options
These are literally the same options as those described for menu entries in the Tk menu documentation. No new lore, just Tk's classics:
-activebackground-activeforeground-background-bitmap-columnbreak-compound-font-foreground-hidemargin-image-indicatoron-label-selectcolor-selectimage-state
Class Specific Options
-bind {uline accel sequence}β the value here is a three element list, and the three pieces are giving very specific energy:ulineβ an integer index of a character to underline in the entry. Does the exact same job as the Tk menu-underlineoption. If this value is an empty string, then no underlining is performed. simple as that πaccelβ a string to display at the right side of the menu entry. Normally it describes an accelerator keystroke sequence that may be typed to invoke the same function as the menu entry. Same function as the Tk menu-acceleratoroption. Empty string? Then no accelerator is displayed. π«sequenceβ a bind sequence that will cause the entry's associated command to fire. π₯
-command cmdprefixβ a command prefix that gets evaluated when the menu entry is invoked. By default the callback is evaluated in the namespace where the install method was executed. Additional values get appended to thecmdprefixand are thus passed to the callback command as arguments β and bestie, those extra arguments depend on what kind of entry you got:- command entry
- The pathname of the toplevel window that invoked the callback.
- checkbutton entry
- The pathname of the toplevel window that invoked the callback.
- The checkbutton's tag name
- The new value for the checkbutton
- radiobutton entry
- The pathname of the toplevel window that invoked the callback.
- The radiobutton's tag name
- The label of the button that was selected
- group entry
- The pathname of the toplevel window that invoked the callback.
- command entry
mBarInst tag.cget pathName tag ?option?
Returns the value of the configuration option given by option, or the value of a user defined tag. π
The option argument can be any of the options accepted by the tag.configure method for that tag type. And user defined tags? You query those without an option value. no cap π«Ά
π― METHODS - GROUP.XXX πΈ
mBarInst group.add tag label ?cmd? ?accel? ?sequence? ?state?
Adds a command to the group with tag name tag. This method appends a new command entry to the end of a command group. The order of the arguments is fixed, but arguments to the right can be ignored β so you can be lazy and leave the tail off. π
Here's what each argument means:
- tag (string) β the tag name of the command group.
- label (string) β the displayed label for the menu entry.
- cmd (string) β a command prefix that will be used for callback command.
- accel (string) β an accelerator string that will be displayed next to the entry label.
- sequence (string) β a bind sequence that will be bound to the callback command.
- state (enum) β sets the active state of the command. One of:
normal,disabled,active
mBarInst group.delete tag label
Deletes a command from a group with tag name tag. Specifically, this method deletes command label from a command group. bye bestie π
mBarInst group.move direction tag label
Changes the position of an entry in a group with tag name tag. The direction argument is the direction ('up' or 'down') the entry will be moved, and the entry that gets moved has the name label. shuffle shuffle β¨
mBarInst group.configure tag label ?option value ...option value?
Configures the options of an entry in the command group with tag name tag.
This method is similar to the tag.configure method, except that it works on entries in a command group. See the documentation for the tag.configure method (above) for more details on command entry options. same energy, different target π―
mBarInst group.serialize tag
Returns a string serialization of the entries in a command group. The argument tag is the tag name for the group that is to be serialized.
The resulting serialization is a list containing three elements: (1) the tag name of the group (2) a dictionary containing group level options (3tk) a list of zero or more similar three element lists that describe the entries in the group. it's giving nesting, and we love that for it πͺ
mBarInst group.deserialize tag stream
Replaces the contents of group tag tag with the commands defined in the serialization stream.
β οΈ The original contents of the group are lost. Gone. Poof. So make sure you actually meant to do that, bestie. π
π METHODS - NOTEBOOK.XXX π¦
mBarInst notebook.addTabStore pathname
This method should be used in code that creates a new notebook tab. Executing it will cause state storage to be allocated for the new notebook tab. The pathname for the notebook tab is passed as an argument to the method. new tab, new storage, new era π
mBarInst notebook.deleteTabStore pathname
This command deallocates the state store for a notebook tab. The pathname for the notebook tab is passed as an argument to the method. spring cleaning fr fr π§Ή
mBarInst notebook.setTabValue pathname tag
This method should be used in the callback for menubar checkbuttons or radiobuttons that have notebook tab scope control. When it's executed, it will move the value associated with tag into the tab store for the tab identified by pathname. β¨
mBarInst notebook.restoreTabValues pathname
This method should be placed in a bind script that is triggered by a notebook's <<NotebookTabChanged>> event. π
π SCOPE CONTROL π
By default a menubar instance looks the same in all installed toplevel windows. As changes are made to one instance of a menubar, all the other instances are immediately updated. That means the internal state of all the menu entries for the instances is synchronized. This behavior is called global scope control of the menubar state. one for all, all for one π
But here's the tea: the menubar class allows finer scope control on check and radio buttons. The scope of these entry types can be modified by adding a modifier character to their type character. Two modifier characters are supported, as shown in the table below.
When the local scope character (@) is added to the definition of a button, the button is given a new variable for each installed toplevel window. This has the effect of making the button's state local to the window (i.e. local scope).
An example use case for this behavior might be a status bar that can be toggled on and off by a checkbutton. The developer may want to allow the user to control the visibility of the status bar on a per window basis. In that case a local modifier would be added to the status bar selector, so the callback code would receive an appropriate value based on the current toplevel window. chef's kiss π
The notebook tab scope character (=) is similar in effect to the local scope character, but it allows a notebook tab selection to also manage the state of a button. Adding the notebook tab scope modifier enables notebook tab scope control β but the developer must then make use of the notebook.xxxx sub-commands to actively manage state values as tabs are added, deleted and selected. you're the main character now, you handle it π
πΈ EXAMPLE πΈ
okay bestie this is the WHOLE thing, a full working demo, no crumbs left. copy it, run it, live your truth β¨
package require Tcl
package require Tk
package require menubar
set tout [text .t -width 25 -height 12]
pack ${tout} -expand 1 -fill both
set mbar [menubar new \
-borderwidth 4 \
-relief groove \
-foreground black \
-background tan \
]
${mbar} define {
File M:file {
Exit C exit
}
Edit M:items+ {
# Label Type Tag Name(s)
# ----------------- ---- ---------
"Cut" C cut
"Copy" C copy
"Paste" C paste
-- S s2
"Options" M:opts {
"CheckList" M:chx+ {
Coffee X coffee+
Donut X donut
Eggs X eggs
}
"RadioButtons" M:btn+ {
"Red" R color
"Green" R color+
"Blue" R color
}
}
}
Help M:help {
About C about
}
}
${mbar} install . {
${mbar} tag.add tout ${tout}
${mbar} menu.configure -command {
# file menu
exit {Exit}
# Item menu
cut {CB Edit cut}
copy {CB Edit copy}
paste {CB Edit paste}
# boolean menu
coffee {CB CheckButton}
donut {CB CheckButton}
eggs {CB CheckButton}
# radio menu
color {CB RadioButton}
# Help menu
about {CB About}
} -bind {
exit {1 Cntl+Q Control-Key-q}
cut {2 Cntl+X Control-Key-x}
copy {0 Cntl+C Control-Key-c}
paste {0 Cntl+V Control-Key-v}
coffee {0 Cntl+A Control-Key-a}
donut {0 Cntl+B Control-Key-b}
eggs {0 Cntl+C Control-Key-c}
about 0
} -background {
exit red
} -foreground {
exit white
}
}
proc pout { txt } {
global mbar
set tout [${mbar} tag.cget . tout]
${tout} insert end "${txt}\n"
}
proc Exit { args } {
puts "Goodbye"
exit
}
proc CB { args } {
set alist [lassign ${args} cmd]
pout "${cmd}: [join ${alist} {, }]"
}
wm minsize . 300 300
wm geometry . +4+4
wm protocol . WM_DELETE_WINDOW exit
wm title . "Example"
wm focusmodel . active
pout "Example started ..."
likeβ¦ look at her. the menubar new with -borderwidth 4, -relief groove, -foreground black, -background tan, then the define block doing the whole menu tree, then install . wiring up commands, binds, background and foreground π
and pout writing into that text widget like it's a lil diary. and Exit? she literally puts "Goodbye" and dips. iconic. π
π CAVEATS π
real talk before you ship this:
- this implementation uses TclOO, so it needs 8.6. no 8.6, no vibes. sorry bestie π
- the code has been tested on Windows (Vista), Linux and OSX (10.4).
π¦ REFERENCES π¦
see also, the receipts:
menuβhttp://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm- A command that creates menubar objects β
http://wiki.tcl.tk/25231
π BUGS, IDEAS, FEEDBACK π
not to be dramatic but this document, and the package it describes, will undoubtedly contain bugs and other problems β that's just the nature of the game, no cap. so please report them in the category menubar of the Tklib Trackers at http://core.tcl.tk/tklib/reportlist π«Ά
and if you have ideas for enhancements β for the package, the docs, or both β please also report those. we want the thoughts. all of them. periodt π
π COPYRIGHT π
Copyright (c) 2009 Tom Krehbiel <krehbiel.tom@gmail.com> All rights reserved.
and that's a wrap on the whole page, bestie π this came from tklib, version 0.5.1, living in section 3tk as menubar(3tk) β go build something cute with it β¨πΈπ¦
π¦ where this page comes from
- debian trixie: tklib 0.9-1
- ubuntu questing: tklib 0.9-1
- ubuntu resolute: tklib 0.9-1build1
- ubuntu stonking: tklib 0.9-1build1
- Copyright (c) 2009 Tom Krehbiel <krehbiel\&.tom@gmail\&.com> All rights reserved\&
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms