Tkinter OptionMenu Widget

The Tkinter OptionMenu widget provides a dropdown list from which the user can select a single item. It’s a convenient way to offer a predefined set of choices without taking up too much space in your graphical user interface (GUI). See how to create and use the OptionMenu widget.

Basic OptionMenu Creation

To create an OptionMenu, you need:

  1. A StringVar to hold the currently selected value.
  2. A list of options to display in the dropdown.
import tkinter as tk

def show_selection():
    selected_option = selected_value.get()
    print(f"Selected: {selected_option}")
    result_label.config(text=f"You chose: {selected_option}")

root = tk.Tk()
root.title("OptionMenu Example")

options = ["Option A", "Option B", "Option C", "Option D"]

selected_value = tk.StringVar(root)
selected_value.set(options[0])  # Set the initial default value

option_menu = tk.OptionMenu(root, selected_value, *options)
option_menu.pack(pady=20)

select_button = tk.Button(root, text="Show Selection", command=show_selection)
select_button.pack(pady=10)

result_label = tk.Label(root, text="No selection yet")
result_label.pack(pady=5)

root.mainloop()

In this example:

  • options is a list of strings that will appear in the dropdown.
  • selected_value = tk.StringVar(root) creates a string variable to store the chosen option.
  • selected_value.set(options[0]) sets the initial value displayed in the OptionMenu.
  • option_menu = tk.OptionMenu(root, selected_value, *options) creates the OptionMenu.
    • The first argument is the parent widget (root).
    • The second argument is the StringVar that will hold the selected value.
    • The *options unpacks the list of options, passing each item as a separate argument to the OptionMenu constructor.
  • The show_selection() function retrieves the current value using selected_value.get().

Executing a Command on Selection Change

You can also configure the OptionMenu to call a function automatically whenever the selection changes, without needing a separate button.

import tkinter as tk

def on_option_change(*args): # *args is required for StringVar trace
    current_selection = selected_value.get()
    print(f"Option changed to: {current_selection}")
    result_label.config(text=f"Current selection: {current_selection}")

root = tk.Tk()
root.title("OptionMenu with Command")

options = ["Apple", "Banana", "Cherry", "Date"]

selected_value = tk.StringVar(root)
selected_value.set(options[0])

# Trace the StringVar to call a function on change
selected_value.trace("w", on_option_change) # "w" means write (when value changes)

option_menu = tk.OptionMenu(root, selected_value, *options)
option_menu.pack(pady=20)

result_label = tk.Label(root, text=f"Current selection: {selected_value.get()}")
result_label.pack(pady=5)

root.mainloop()

Here:

  • selected_value.trace("w", on_option_change) registers a callback function (on_option_change) to be executed whenever the StringVar’s value is written to (“w”).
  • The on_option_change function must accept *args because the trace mechanism passes extra arguments (name, index, mode) to the callback.
See also  Using Tkinter Frame with the grid geometry manager in Python GUI development

Adding/Removing Options Dynamically

You can dynamically add or remove options from an OptionMenu by modifying its underlying menu.

import tkinter as tk

def add_option():
    new_option = f"New Option {len(options) + 1}"
    options.append(new_option)
    update_option_menu()

def remove_option():
    if len(options) > 1:
        options.pop()
        if selected_value.get() not in options and options: # If removed selected, set to first
            selected_value.set(options[0])
        elif not options: # If no options left
            selected_value.set("") # Or disable the menu
        update_option_menu()

def update_option_menu():
    option_menu['menu'].delete(0, 'end') # Clear existing options
    for option in options:
        option_menu['menu'].add_command(label=option, command=tk._set_option_menu(selected_value, option))

root = tk.Tk()
root.title("Dynamic OptionMenu")

options = ["Item 1", "Item 2"]
selected_value = tk.StringVar(root)
selected_value.set(options[0])

option_menu = tk.OptionMenu(root, selected_value, *options)
option_menu.pack(pady=10)

add_button = tk.Button(root, text="Add Option", command=add_option)
add_button.pack(pady=5)

remove_button = tk.Button(root, text="Remove Option", command=remove_option)
remove_button.pack(pady=5)

root.mainloop()

This advanced example demonstrates how to clear and re-populate the OptionMenu’s internal menu when the list of options changes.

See also  Effortlessly Select Files with Tkinter's askopenfilename

Key Points

  • Always use a tk.StringVar to manage the selected value.
  • Pass the StringVar and then unpack your list of options (*options) to the OptionMenu constructor.
  • Use StringVar.trace("w", callback_function) to execute code when the selection changes.
  • Dynamically modifying options requires direct manipulation of the OptionMenu’s internal menu.

The OptionMenu widget is a simple yet effective way to present a list of choices to the user in a compact manner.

See also  Updating Label Text in Tkinter