Drop-down List (Combobox) in Tk (tkinter)

The drop-down list is known in the GUI jargon as Combobox, since it is a combo between a listbox and a textbox. Thus, it can act as a drop-down list with predefined options and might also allow the user to type a value that is not in the list.

/images/drop-down-list-combobox-in-tk-tkinter/combobox-tkinter.png

The widget was introduced in Tk 8.5 and is provided via the ttk.Combobox class, which inherits from the textbox widget ttk.Entry, so all operations applicable to a textbox also apply to a combobox.

The following code creates a simple window with an empty drop-down list.

from tkinter import ttk
import tkinter as tk
main_window = tk.Tk()
main_window.config(width=300, height=200)
main_window.title("Combobox")
combo = ttk.Combobox()
combo.place(x=50, y=50)
main_window.mainloop()

If we want the widget to behave only as a drop-down list, thus not allowing the user to enter their own values, we instantiate it as read-only:

combo = ttk.Combobox(state="readonly")

To configure a set of options, we pass a list to the values argument:

combo = ttk.Combobox(
    state="readonly",
    values=["Python", "C", "C++", "Java"]
)

A combobox in Tk only works with strings. Other data types will be automatically converted before being added to the list.

The get() method returns the selected option, either if it has been picked from the list or manually written by the user (if the widget is not read-only). For example, the following code uses a message box to display the selected option in the drop-down list after pressing a button.

from tkinter import messagebox, ttk
import tkinter as tk
def display_selection():
    # Get the selected value.
    selection = combo.get()
    messagebox.showinfo(
        message=f"The selected value is: {selection}",
        title="Selection"
    )
main_window = tk.Tk()
main_window.config(width=300, height=200)
main_window.title("Combobox")
combo = ttk.Combobox(
    state="readonly",
    values=["Python", "C", "C++", "Java"]
)
combo.place(x=50, y=50)
button = ttk.Button(text="Display selection", command=display_selection)
button.place(x=50, y=100)
main_window.mainloop()

The get() method always returns a string. If there is no selection, an empty string is returned.

It is also possible to get the index (i.e., the position of an option within the list, starting from 0) of the selected element via the current() method. If no element is selected, or if the element is not among the provided options (that is, it has been typed by the user), the return value is -1.

# Get the index of the currently selected option.
index = combo.current()

Similarly, the set() method sets the currently selected option.

# Select an option.
combo.set("Python")

To select an option by position or index, the current() method is also used, although passing the element to be selected as an argument:

# Select an option by index ("C++").
combo.current(2)

To get all the options configured in the drop-down:

# Returns ('Python', 'C', 'C++', 'Java')
values = combo["values"]

Note that the returned value is a tuple, not a list. To add an option without dropping those already in the drop-down, use:

values = list(combo["values"])
combo["values"] = values + ["New option"]

And to remove all the options:

# Empty the list.
combo["values"] = []

Events

The ttk.Combobox widget introduces a new event called <<ComboboxSelected>> that is sent when the selected option changes. This way, it is possible to set up a function to be executed every time the user changes the drop-down selection. For example:

from tkinter import messagebox, ttk
import tkinter as tk
def selection_changed(event):
    selection = combo.get()
    messagebox.showinfo(
        title="New Selection",
        message=f"Selected option: {selection}"
    )
main_window = tk.Tk()
main_window.config(width=300, height=200)
main_window.title("Combobox")
combo = ttk.Combobox(values=["Python", "C", "C++", "Java"])
combo.bind("<<ComboboxSelected>>", selection_changed)
combo.place(x=50, y=50)
main_window.mainloop()
/images/drop-down-list-combobox-in-tk-tkinter/combobox-selection.gif

Note that this event does not record changes entered manually by the user.

We can pass a function to the postcommand parameter to get notified when the drop-down has been opened (i.e., the arrow on right has been pressed):

from tkinter import ttk
import tkinter as tk
def dropdown_opened():
    print("The drop-down has been opened!")
main_window = tk.Tk()
main_window.config(width=300, height=200)
main_window.title("Combobox")
combo = ttk.Combobox(
    values=["Python", "C", "C++", "Java"],
    postcommand=dropdown_opened
)
combo.place(x=50, y=50)
main_window.mainloop()

Comments