The bind Command
The bind command attaches a Tcl script to a specific event on a specific widget, using the form bind widgetPath eventSequence script—for example, bind .b <Button-1> {puts "clicked"} runs the script whenever the left mouse button is pressed while the pointer is over .b. Event sequences are written inside angle brackets, such as <Button-1> for a mouse click, <KeyPress-Return> for the Enter key, <Motion> for pointer movement, or <Configure> for a resize event, and Tk recognizes dozens of built-in event types covering mouse, keyboard, window, and focus events. Inside the bound script, Tk performs percent substitution, replacing sequences like %x and %y with the event's coordinates or %W with the path name of the widget the event occurred on, before the script is evaluated, which is how a single generic handler can still access details specific to the particular event that triggered it.
Cricket analogy: bind .b <Button-1> {...} wiring a click to a script is like a third umpire's protocol wired to trigger a specific replay review only when a specific on-field signal (the TV signal for a run-out) is shown—one exact trigger maps to one exact response.
button .b -text "Click Me"
pack .b
bind .b <Button-1> {
puts "Clicked at (%x,%y) on widget %W"
}
entry .search
pack .search
bind .search <KeyPress-Return> {
runSearch [%W get]
}
Event Sequences and Modifiers
Event sequences can combine a modifier with a base event, such as <Control-s> for Ctrl+S, <Shift-Button-1> for a shift-click, or <Double-Button-1> for a double-click, and Tk also recognizes Triple- for triple-clicks and platform modifiers like Command on macOS or Alt on Windows/Linux. Beyond raw hardware events, Tk defines virtual events—written with double angle brackets like <<Copy>>, <<Paste>>, or <<ListboxSelect>>—which decouple a logical action from the specific key combination that triggers it; a text widget generates <<Copy>> when the user presses Ctrl+C on Windows/Linux or Command+C on macOS, so application code can bind to the single virtual event instead of writing separate platform-specific bindings for the same intent.
Cricket analogy: A virtual event like <<Copy>> decoupled from a specific key combo is like DRS being triggered by the same umpire request gesture regardless of which specific broadcaster's technology implements the review underneath.
Return the literal value break from inside a binding script to stop the event from propagating to lower-priority bind tags (for example, to prevent a widget-level binding from also triggering the default class binding). Without break, Tk runs the bindings for every applicable bind tag in sequence for the same event.
Percent Substitutions and the Event Object
Beyond %x, %y, and %W, Tk's percent substitutions expose many other event fields: %K gives the symbolic name of the key pressed (e.g. Return, Escape, a), %A gives the printable character generated by a keypress (useful for handling arbitrary typed text), %b gives the mouse button number, and %h/%w give the new height and width on a <Configure> (resize) event. Because these substitutions happen as textual replacement before the script is evaluated, values that might contain special characters—like %A producing a literal { or $—can break script syntax if inserted carelessly, so production code typically wraps the substituted values as a single safely-quoted argument to a procedure, e.g. bind .e <KeyPress> {handleKey %K %A}, rather than interpolating them directly into arbitrary Tcl code.
Cricket analogy: %K reporting the symbolic key name is like a match report logging the specific delivery type (yorker, bouncer) rather than just noting that 'a ball was bowled'—the substitution gives you the specific identity of what happened.
bind .canvas <Motion> {
.status configure -text "Pointer at (%x, %y) on %W"
}
bind .entry <KeyPress> {
handleKey %K %A
}
proc handleKey {keysym char} {
if {$keysym eq "Escape"} {
.entry delete 0 end
}
}
Bind Tags and Event Propagation
Every widget carries an ordered list of bind tags, retrievable and settable with bindtags widgetPath, and by default that list is {widgetPath widgetClass toplevelPath all}—meaning an event first checks bindings on the specific widget instance, then on its widget class (so all Button widgets share class-level behavior), then on its containing toplevel window, and finally on the special all tag shared by every widget in the application. When an event fires, Tk runs the matching binding script for each tag in that order, and unless a script explicitly returns break, execution continues on to the next tag's binding, which is how a single click can simultaneously update a status bar (bound at the all level) and run a widget-specific command (bound at the instance level). You can insert a custom bind tag into this list with bindtags .b [linsert [bindtags .b] 1 myCustomTag] and then attach bindings to that tag name directly, giving you a reusable behavior that can be shared across many otherwise-unrelated widgets.
Cricket analogy: The ordered bind-tag chain (widget, class, toplevel, all) is like a review escalation order in cricket—on-field umpire first, then TV umpire, then match referee—each level gets a chance to act on the same incident unless the decision is finalized (break) earlier in the chain.
Binding directly on a widget class, e.g. bind Button <Button-1> {...}, affects every Button widget in the entire application, including ones created by third-party libraries you didn't write. Prefer binding on the specific widget instance path, or insert a dedicated custom bind tag, so you don't accidentally override behavior for unrelated buttons.
- bind widgetPath eventSequence script attaches a Tcl script to a specific event on a specific widget.
- Event sequences combine modifiers (Control, Shift, Double, Triple) with a base event inside angle brackets, e.g. <Control-s> or <Double-Button-1>.
- Virtual events like <<Copy>> and <<Paste>> decouple a logical action from platform-specific key combinations.
- Percent substitutions (%x, %y, %W, %K, %A, %b, %h, %w) inject event-specific details into the bound script.
- Returning break from a binding script stops the event from propagating to lower-priority bind tags.
- Every widget has an ordered bindtags list (instance, class, toplevel, all); events run through each tag's bindings in order.
- Custom bind tags can be inserted into a widget's bindtags list to share reusable behavior across otherwise unrelated widgets.
Practice what you learned
1. What does the event sequence <Double-Button-1> represent?
2. What is the purpose of returning break from inside a bound script?
3. Which percent substitution gives the symbolic name of the key that was pressed, such as Return or Escape?
4. What is a key benefit of virtual events like <<Copy>> over binding directly to <Control-c>?
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.
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.
Menus and Dialogs in Tk
Building application menu bars and menus with the menu widget, plus using Tk's standard dialog commands for messages, files, and colors.
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