Building a Menu Bar
A Tk application's menu bar is built from menu widgets: you create a top-level menu with menu .menubar, attach it to the window using . configure -menu .menubar, and then populate it with cascading submenus—menu .menubar.file followed by .menubar add cascade -label File -menu .menubar.file—so the menu bar itself contains only cascades, while each cascade menu holds the actual clickable entries. Entries within a menu are added with add command -label "Open..." -command openFile -accelerator "Ctrl+O", where -accelerator only displays the shortcut text next to the label and does not itself bind the key—you still need a separate bind . <Control-o> openFile for the shortcut to actually work—and add separator inserts a thin dividing line to visually group related entries, such as separating Save and Save As... from Exit.
Cricket analogy: A menu bar containing only cascades that expand into real entries is like a match scorecard's top-level tabs—Batting, Bowling, Fielding—each of which expands to the actual detailed stats when selected, rather than showing every stat flatly on one screen.
menu .menubar
. configure -menu .menubar
menu .menubar.file -tearoff 0
.menubar add cascade -label "File" -menu .menubar.file
.menubar.file add command -label "Open..." -command openFile -accelerator "Ctrl+O"
.menubar.file add command -label "Save" -command saveFile -accelerator "Ctrl+S"
.menubar.file add separator
.menubar.file add command -label "Exit" -command {destroy .}
bind . <Control-o> openFile
bind . <Control-s> saveFile
Checkbutton and Radiobutton Menu Entries
Menu entries aren't limited to plain commands: add checkbutton -label "Word Wrap" -variable wrapVar -onvalue 1 -offvalue 0 puts a toggleable checkmark entry in the menu that stays synced to a Tcl variable exactly like a checkbutton widget does, and add radiobutton -label "12pt" -variable fontSizeVar -value 12 lets several radiobutton entries share one variable so only one can be checked at a time, useful for a font-size or view-mode submenu. Submenus are just cascades pointing at another menu widget, so a deeply nested structure like View > Zoom > 100% is built by creating .menubar.view, then .menubar.view.zoom, then adding add cascade -label Zoom -menu .menubar.view.zoom inside the view menu, and finally adding the individual zoom-level radiobutton entries inside the zoom menu itself.
Cricket analogy: Radiobutton menu entries sharing one variable, where selecting 12pt deselects 10pt, is like a broadcaster's single preferred-camera-angle setting where choosing the bowler's-end camera automatically deselects the square-leg camera option.
Passing -tearoff 0 when creating a menu (as in menu .menubar.file -tearoff 0) removes the dashed tear-off line that some platforms show at the top of a menu by default, which historically let users detach a menu into its own floating window. Most modern applications disable tear-off menus since the feature is rarely used and looks dated.
Context Menus and Popups
Context menus—the menu that appears on a right-click—are built the same way as a menu bar's submenus, as a standalone menu widget that isn't attached to any cascade, and are shown on demand with tk_popup .contextMenu $x $y, which posts the menu at the given screen coordinates and handles all the platform-specific details of positioning and dismissing it. The typical pattern binds the right mouse button (<Button-3> on Windows/Linux, though it's <Button-2> on some older Mac configurations, which is why cross-platform code often binds both) to a small procedure that calls tk_popup .contextMenu %X %Y, using the uppercase %X/%Y substitutions for screen-relative coordinates rather than the lowercase %x/%y, which are relative to the widget instead and would position the popup incorrectly.
Cricket analogy: tk_popup posting a menu at an exact screen coordinate on demand is like a broadcast graphics operator triggering a stats overlay to appear at a precise spot on screen only when a specific replay moment calls for it, not as a permanent fixture.
Standard Dialogs
Tk ships several ready-made modal dialogs so you don't have to hand-build common interactions: tk_messageBox -message "Delete this file?" -type yesno -icon warning shows a message with standard buttons and returns which button was pressed (yes or no) as its result; tk_getOpenFile and tk_getSaveFile show the platform's native file-picker and return the chosen path (or an empty string if canceled); and tk_chooseColor shows a color picker and returns the selected color as a hex string like #3a7bd5. Because these are modal dialogs, the Tcl script calling them blocks at that line until the user responds—the dialog commands don't return until the dialog is dismissed—which is exactly the behavior you want for a confirmation prompt, since the calling code typically needs the user's answer immediately before deciding whether to proceed with deleting the file or discarding the changes.
Cricket analogy: A modal tk_messageBox blocking execution until answered is like the third umpire's review process pausing play entirely—no more deliveries are bowled until the on-field decision is confirmed or overturned.
tk_messageBox, tk_getOpenFile, tk_getSaveFile, and tk_chooseColor are all modal and platform-native, meaning their exact visual appearance differs between Windows, macOS, and Linux and cannot be restyled with ttk themes. If you need a dialog with custom widgets or a non-native look, build it yourself as a toplevel window with grab set to make it modal, rather than trying to reskin these standard commands.
- A menu bar is a menu widget attached to a toplevel with configure -menu; cascades link submenus, and add command/checkbutton/radiobutton/separator populate entries.
- -accelerator only displays shortcut text; the actual key combination must be bound separately with bind.
- add checkbutton and add radiobutton menu entries sync to a Tcl variable exactly like their standalone widget counterparts.
- -tearoff 0 removes the dated tear-off dashed line from a menu.
- Context menus are standalone menu widgets shown on demand with tk_popup .menu %X %Y, using screen-relative uppercase coordinates.
- tk_messageBox, tk_getOpenFile, tk_getSaveFile, and tk_chooseColor are built-in modal, platform-native dialogs that block until the user responds.
- Custom-styled modal dialogs must be hand-built as a toplevel with grab set, since the standard dialog commands can't be restyled.
Practice what you learned
1. What does the -accelerator option on a menu entry actually do?
2. Which pair of percent substitutions should be used with tk_popup to correctly position a context menu at the mouse location?
3. What does -tearoff 0 do when creating a menu?
4. Why can't tk_messageBox be restyled with a ttk theme?
Was this page helpful?
You May Also Like
Tk Widgets Overview
A tour of the core Tk widget classes—labels, buttons, entries, frames, and containers—and how they fit into a Tcl/Tk application's widget tree.
Event Binding in Tk
How Tk's bind command connects user input and window events to Tcl scripts, including event sequences, substitutions, and bind tags.
Buttons, Labels, and Entry Widgets
The three most common Tk input/display widgets—button, label, and entry—covering their key options, variable linkage, and validation.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics