Listas desplegables y listas de selección en Tkinter
En este artículo exploraremos dos de los widgets más útiles para presentar opciones al usuario en aplicaciones de escritorio con Tkinter: Listbox y ttk.Combobox. Veremos su funcionamiento, casos de uso, cómo cargar datos de forma dinámica y terminaremos con un ejercicio práctico.
Listbox – Selección simple y múltiple
El widget Listbox muestra una lista vertical de elementos. Cada elemento ocupa una fila y el usuario puede seleccionar una o varias filas según la configuración.
Configuración básica
import tkinter as tk
root = tk.Tk()
listbox = tk.Listbox(root, height=6, selectmode=tk.SINGLE) # SINGLE | BROWSE | MULTIPLE | EXTENDED
listbox.pack(padx=10, pady=10)
root.mainloop()
Modos de selección:
tk.SINGLE: solo una fila a la vez.tk.BROWSE: similar a SINGLE pero permite mover la selección con el mouse arrastrado.tk.MULTIPLE: el usuario puede marcar/desmarcar filas individualmente (con Ctrl o clic).tk.EXTENDED: permite rangos de selección con Shift y combinaciones con Ctrl (el más usado para selección múltiple).
Cargar datos dinámicamente
Supongamos que queremos presentar una lista de materias que proviene de una base de datos o de un archivo CSV. Podemos rellenar el Listbox con un bucle:
materias = ["Matemáticas", "Física", "Química", "Historia", "Literatura"]
for materia in materias:
listbox.insert(tk.END, materia)
Para actualizar la lista sin recrear el widget, basta vaciarla y volver a insertar:
def actualizar_lista(nuevas_opciones):
listbox.delete(0, tk.END) # elimina todo
for opt in nuevas_opciones:
listbox.insert(tk.END, opt)
Obtener la(s) selección(es)
seleccion = [listbox.get(i) for i in listbox.curselection()]
print("Seleccionado:", seleccion)
En modo EXTENDED curselection() devuelve una tupla con los índices de todas las filas seleccionadas.
Mejores prácticas y troubleshooting
- Scroll automático: si la lista puede crecer mucho, añada una barra de desplazamiento vinculada:
scroll = tk.Scrollbar(root, orient=tk.VERTICAL, command=listbox.yview) listbox.config(yscrollcommand=scroll.set) scroll.pack(side=tk.RIGHT, fill=tk.Y) - Validación de selección: siempre compruebe que
listbox.curselection()no esté vacío antes de procesar. - Rendimiento: para listas con miles de elementos, utilice
listbox.inserten bloques o considerettk.Treeviewcon vista de tabla.
ttk.Combobox – Selección de una única opción
El ttk.Combobox combina la funcionalidad de un Entry editable y una lista desplegable. Por defecto permite seleccionar **una** opción, pero también puede configurarse como read‑only para impedir la edición libre.
Creación básica
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
combobox = ttk.Combobox(root, values=["Opción 1", "Opción 2", "Opción 3"], state="readonly")
combobox.current(0) # selecciona la primera opción
combobox.pack(padx=10, pady=10)
root.mainloop()
Los parámetros clave son:
values: lista o tuple de opciones.state:"readonly"para bloquear la edición,"normal"para permitir al usuario escribir texto libremente.
Carga dinámica de opciones (ejemplo de cursos)
Supongamos que obtenemos la lista de cursos desde una API REST o un fichero JSON. Podemos actualizar el Combobox en tiempo real:
import json
# Simulación de carga desde archivo JSON
with open('cursos.json') as f:
datos = json.load(f)
cursos = [c['nombre'] for c in datos['cursos']]
combobox['values'] = cursos
if cursos:
combobox.current(0)
Para recargar bajo demanda (por ejemplo, al pulsar un botón "Actualizar"):
def refrescar():
nuevos = obtener_cursos_desde_api()
combobox['values'] = nuevos
combobox.set('') # vacía la selección actual
btn = ttk.Button(root, text="Actualizar", command=refrescar)
btn.pack(pady=5)
Obtener la opción seleccionada
seleccion = combobox.get()
print("Curso seleccionado:", seleccion)
Comparativa con Listbox
| Característica | Listbox | ttk.Combobox |
|---|---|---|
| Selección múltiple | Sí (EXTENDED, MULTIPLE) | No |
| Edición directa del valor | No | Sí (state="normal") |
| Scroll integrado | Necesita Scrollbar externa | Automático al desplegar |
| Uso típico | Listas largas, selección de varios ítems | Selección única de opciones predefinidas |
Buenas prácticas y solución de problemas comunes
- Valores vacíos: Si el
Comboboxse crea convalues=[], la lista desplegable aparecerá vacía. Asegúrese de actualizarvaluesantes de llamar acurrent(). - Sincronización con otras UI: Cuando el valor del combobox controla la carga de otro widget (por ejemplo, una
Listboxde módulos del curso), use el evento'>'para reaccionar.def on_curso_change(event): curso = combobox.get() modulos = cargar_modulos(curso) actualizar_listbox(modulos) combobox.bind('>', on_curso_change) - Accesibilidad: Añada
tooltipolabeldescriptivo para lectores de pantalla.
Ejercicio final propuesto
Desarrolla una pequeña aplicación "Gestor de Inscripciones" con los requisitos siguientes:
- Al iniciar, carga dinámicamente una lista de carreras desde un archivo
carreras.jsony muéstralas en unttk.Combobox(solo una selección). - Cuando el usuario elija una carrera, carga en un
Listboxlos asignaturas correspondientes (puede seleccionar varias asignaturas). - Incluye un botón “Inscribir” que, al pulsarse, muestra en un
tkinter.messageboxla carrera elegida y la lista de asignaturas seleccionadas. - Implementa validación: si no se ha seleccionado carrera o asignaturas, muestra una advertencia al usuario.
- Opcional: agrega una barra de progreso que simule la “carga” de datos desde una API (usa
time.sleepen un hilo separado para no bloquear la UI).
Este ejercicio consolida los conceptos de:
- Uso de
ttk.ComboboxyListboxen conjunto. - Carga dinámica de datos y actualización de widgets.
- Manejo de eventos y validación de entrada.
- Buenas prácticas de arquitectura (separar lógica de carga de datos de la UI).
¡Anímate a implementarlo y comparte tu solución en los foros de la comunidad!