tkinter Combobox select next value instead of showing the whole list when pressing arrow keys

Question:

I have several tkinter Comboboxes in my python application with the default tkinter behaviour that the ‘up’ arrow does nothing and the ‘down’ arrow shows the whole list of values, which can then be reaverserd with the arrow keys.
However, I would like to ‘scroll’ through the Comboboxes with the arrow keys without this list popping up (i.e. arrow down directly switches to the next element, arrow up directly switches to the previous element).

MWE of Combobox:

import tkinter as tk
import tkinter.ttk as ttk

app = tk.Tk()
combo = ttk.Combobox(app, values = [f"item {i}" for i in range(20)])
combo.grid()

(How) can I achieve this desired behaviour? Do I have to catch the key events or is there some setting that I’m missing?

Asked By: Xoriun

||

Answers:

Here’s a solution that should work for both Up and Down

import tkinter as tk
import tkinter.ttk as ttk


def select_next(event):
    selection = combo.current()  # get the current selection
    last = len(combo['values']) - 1  # index of last item
    key = event.keysym  # get the key that was pressed
    if key == 'Up':
        try:
            combo.current(selection - 1)  # set the combobox to the previous item
        except tk.TclError:  # end of list reached
            combo.current(last)  # wrap around to last item
    elif key == 'Down':
        try:  
            combo.current(selection + 1)  # set the combobox to the next item
        except tk.TclError:  # end of list reached
            combo.current(0)   # wrap around to first item
    return 'break'  # tell tk to dispose of this event and don't show the menu!


app = tk.Tk()
combo = ttk.Combobox(app, values = [f"item {i}" for i in range(20)])
combo.grid()
combo.current(0)  # select the first item by default
combo.bind('<Up>', select_next)  # up arrow
combo.bind('<Down>', select_next)  # down arrow
Answered By: JRiggles
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.