Tkinter OptionMenu displays one selected value and opens a menu containing predefined choices. It is useful when the user must choose exactly one option and the choices do not need to remain visible all the time.

An OptionMenu is connected to a Tkinter variable such as StringVar. The variable stores the currently selected value.
import tkinter as tk
root=tk.Tk()
root.geometry('350x200')
root.title('Tkinter OptionMenu - plus2net')
selected=tk.StringVar(value='HTML')
tk.Label(root, text='Select Language').grid(row=0, column=0, padx=10, pady=20)
option_menu=tk.OptionMenu(root, selected, 'HTML', 'PHP', 'MySQL', 'Python')
option_menu.grid(row=0, column=1, padx=10, pady=20)
root.mainloop()
The general form is:
tk.OptionMenu(parent, variable, value1, value2, ...)
The connected variable should usually contain an initial value before the widget is displayed.
The variable can initially contain text that is not one of the selectable menu entries.
selected=tk.StringVar(value='Select a language')
option_menu=tk.OptionMenu(root, selected, 'HTML', 'PHP', 'Python')
The placeholder is displayed initially, but it is not itself a menu choice unless it is included among the OptionMenu values.
Use the unpacking operator * to pass elements of a Python list as individual OptionMenu values.
languages=['PHP', 'MySQL', 'Python', 'HTML']
selected=tk.StringVar(value=languages[0])
option_menu=tk.OptionMenu(root, selected, *languages)
This:
*languages
passes each list element separately to the constructor.
tk.OptionMenu needs at least one menu value when it is created. If your data source can return an empty list, check it before constructing the widget.Read the connected StringVar:
value=selected.get()
print(value)

import tkinter as tk
def show_value():
output_var.set(selected.get())
root=tk.Tk()
root.geometry('420x180')
selected=tk.StringVar(value='HTML')
output_var=tk.StringVar(value='Output')
option_menu=tk.OptionMenu(root, selected, 'HTML', 'PHP', 'MySQL', 'Python')
option_menu.grid(row=0, column=0, padx=10, pady=20)
tk.Button(root, text='Show Value', command=show_value).grid(row=0, column=1, padx=10)
tk.Label(root, textvariable=output_var).grid(row=0, column=2, padx=10)
root.mainloop()
OptionMenu supports a command callback. The selected value is passed to the callback.
import tkinter as tk
def option_selected(value):
output_var.set(value)
root=tk.Tk()
selected=tk.StringVar(value='HTML')
output_var=tk.StringVar()
option_menu=tk.OptionMenu(
root,
selected,
'HTML',
'PHP',
'MySQL',
'Python',
command=option_selected
)
option_menu.pack(pady=10)
tk.Label(root, textvariable=output_var).pack(pady=10)
root.mainloop()
If the user chooses Python, the callback receives:
'Python'
This is usually the simplest approach when the program needs to respond specifically to a user's menu selection.

trace_add() monitors writes to the connected variable.
def value_changed(*args):
output_var.set(selected.get())
selected.trace_add('write', value_changed)
import tkinter as tk
def value_changed(*args):
output_var.set(selected.get())
root=tk.Tk()
values=['PHP', 'MySQL', 'Python', 'HTML']
selected=tk.StringVar(value=values[0])
output_var=tk.StringVar()
option_menu=tk.OptionMenu(root, selected, *values)
option_menu.pack(pady=10)
tk.Label(root, textvariable=output_var).pack(pady=10)
selected.trace_add('write', value_changed)
root.mainloop()
| Approach | Use |
|---|---|
command=callback | Respond when the user chooses an OptionMenu item. |
StringVar.trace_add('write', ...) | Respond whenever the variable is written, including programmatic changes. |
For example:
selected.set('Python')
updates the OptionMenu and triggers a write trace. A programmatic set() is different from the user selecting a menu command.
Because OptionMenu is linked to a Tkinter variable, change the displayed selection with set().
selected.set('Python')
Read it again with:
print(selected.get())
selected.set('HTML')
selected.set('Select a language')
A dictionary is useful when the user should see readable text but the application needs an ID or code.
For example:
languages={
'en': 'English',
'es': 'Spanish',
'fr': 'French',
'de': 'German',
'it': 'Italian'
}
The menu can display the dictionary values:
selected=tk.StringVar(value=languages['es'])
option_menu=tk.OptionMenu(root, selected, *languages.values())
Create a reverse lookup once instead of looping through the entire dictionary every time the user changes the selection.
name_to_code={name: code for code, name in languages.items()}
import tkinter as tk
languages={
'en': 'English',
'es': 'Spanish',
'fr': 'French',
'de': 'German',
'it': 'Italian'
}
name_to_code={name: code for code, name in languages.items()}
def language_selected(name):
code_label.config(text=name_to_code[name])
root=tk.Tk()
selected=tk.StringVar(value=languages['es'])
tk.Label(root, text='Language').grid(row=0, column=0, padx=5, pady=10)
option_menu=tk.OptionMenu(root, selected, *languages.values(), command=language_selected)
option_menu.grid(row=0, column=1)
code_label=tk.Label(root, text='es', bg='yellow', width=6)
code_label.grid(row=0, column=2, padx=5)
root.mainloop()
The user sees:
Spanish
while the application can obtain:
es
Use Python's sorted() when you want a sorted copy without modifying the original list.
languages=['PHP', 'MySQL', 'Python', 'HTML', 'jQuery']
sorted_languages=sorted(languages, key=str.casefold)
selected=tk.StringVar(value=sorted_languages[0])
option_menu=tk.OptionMenu(root, selected, *sorted_languages)
list.sort() is also valid, but it changes the original list in place.

The visible OptionMenu button and its dropdown Menu can use different fonts.
import tkinter as tk
root=tk.Tk()
selected=tk.StringVar(value='HTML')
option_menu=tk.OptionMenu(root, selected, 'HTML', 'PHP', 'MySQL', 'Python')
option_menu.pack(padx=20, pady=20)
option_menu.config(font=('Arial', 20))
option_menu['menu'].config(font=('Arial', 14))
root.mainloop()
This controls the visible button:
option_menu.config(font=('Arial', 20))
This controls the dropdown choices:
option_menu['menu'].config(font=('Arial', 14))
Classic tk.OptionMenu is built from a Menubutton and an associated Menu.
Access the Menu with:
menu=option_menu['menu']
You can then use normal Tkinter Menu methods.
print(menu.index('end'))
menu=option_menu['menu']
menu.insert_separator(2)
This inserts a separator at menu index 2, so it appears after the first two existing menu entries.
Because OptionMenu uses an ordinary Tkinter Menu, its choices can be rebuilt dynamically.
new_values=['Java', 'Python', 'PHP']
menu=option_menu['menu']
menu.delete(0, 'end')
for value in new_values:
menu.add_command(label=value, command=lambda v=value: selected.set(v))
selected.set(new_values[0])
v=value? It stores the current loop value in each lambda. Without it, all commands could refer to the final value after the loop ends.If your interface depends on a trace_add() callback, changing selected with set() will continue to trigger that trace.
option_menu['menu'].delete(0, 'end')
selected.set('')
option_menu.config(state=tk.DISABLED)
option_menu.config(state=tk.NORMAL)
This is useful when another selection must be made before the OptionMenu becomes available.
Display OptionMenu configuration names with:
print(option_menu.keys())
For detailed configuration information:
print(option_menu.config())
The underlying dropdown Menu has its own options:
print(option_menu['menu'].keys())
| Widget | Best Use | User Can Type? | Multiple Selection? |
|---|---|---|---|
| OptionMenu | Simple compact fixed-choice dropdown. | No | No |
| ttk.Combobox | Themed compact dropdown with editable or readonly modes. | Yes in normal state | No |
| Listbox | Choices should remain visible or several items may be selected. | No | Yes |
You want a themed ttk control, or you need the choice between editable normal mode and restricted readonly mode.
Typing into a normal Combobox changes its Entry text. It should not be described as automatically opening the dropdown simply because the user starts typing.
The user benefits from seeing several choices simultaneously, needs scrolling through a visible list, or must select multiple items.
This tutorial primarily uses the classic:
tk.OptionMenu()
Tkinter also provides a themed OptionMenu:
from tkinter import ttk
selected=tk.StringVar()
option_menu=ttk.OptionMenu(root, selected, 'HTML', 'HTML', 'PHP', 'Python')
The ttk version follows the platform's themed widget system and has a somewhat different constructor and styling model. Python documents it separately from the classic Tk OptionMenu. :contentReference[oaicite:2]{index=2}
Practice modifying the options available in an existing OptionMenu.
Add or Remove OptionMenu ChoicesTake input from the user and add the new text as an OptionMenu choice.
Add User Input to OptionMenuCollect unique class values from the student table and use the records as dropdown choices.
OptionMenu Values from MySQLOptionMenu selection is tied to a Tkinter variable such as:
selected=tk.StringVar(value='Python')
Read and change the current value through this variable.
This will fail when values is empty:
option_menu=tk.OptionMenu(root, selected, *values)
Check the list before construction when options come from a file or database.
For a function that should run only when the user chooses a menu item:
option_menu=tk.OptionMenu(root, selected, *values, command=option_selected)
is often clearer.
Use:
selected.trace_add('write', callback)
when programmatic set() changes must also be observed.
Instead of repeatedly looping through all key-value pairs, create a reverse lookup when display values are unique.
This mutates the list:
values.sort()
This creates a sorted copy:
sorted_values=sorted(values)
This changes the displayed variable:
selected.set('Java')
but does not automatically add Java to the dropdown Menu.
The OptionMenu and its dropdown Menu are separate widgets for styling purposes.
option_menu.config(font=('Arial', 18))
option_menu['menu'].config(font=('Arial', 14))
A Combobox accepts typed values in normal state. In readonly state, users are restricted to configured choices.
OptionMenu selects one value. Use Listbox with an appropriate multiple-selection mode when several choices are required.
tk.OptionMenu provides a compact menu of mutually exclusive choices.StringVar.get() to read the current value.StringVar.set() to change the displayed value.*my_list to unpack a Python list into menu options.command=callback to react to a user's selection.trace_add('write', ...) when all changes to the connected variable must be monitored.trace_add() also reacts to programmatic set() calls.sorted() to create sorted options without modifying the original list.option_menu['menu'].Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.