Lista desplegable (Combobox) en Tcl/Tk (tkinter)

Lista desplegable (Combobox) en Tcl/Tk (tkinter)



En la jerga del desarrollo de interfaces de usuario se lo conoce como Combobox, pues se trata de una combinación entre una lista y una caja de texto. Así, puede actuar como una lista desplegable con determinadas opciones y, opcionalmente, permitir al usuario escribir un valor que no se encuentre en la lista.

Lista desplegable (Combobox) en Tcl/Tk (tkinter)

Fue introducido en Tk 8.5 y se provee a través de la clase ttk.Combobox, la cual hereda de ttk.Entry, por lo que todas las operaciones aplicables a una caja de texto también aplican para un combobox.

El siguiente código crea una simple ventana con una lista desplegable vacía.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from tkinter import ttk
import tkinter as tk

class Application(ttk.Frame):
    
    def __init__(self, main_window):
        super().__init__(main_window)
        main_window.title("Combobox")
        
        self.combo = ttk.Combobox(self)
        self.combo.place(x=50, y=50)
        
        main_window.configure(width=300, height=200)
        self.place(width=300, height=200)

main_window = tk.Tk()
app = Application(main_window)
app.mainloop()

Para evitar que el usuario ingrese sus propios valores, es decir, que el control se comporte únicamente como una lista desplegable y no como una caja de texto, utilizamos:

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

Para añadir un conjunto de opciones, asignamos una lista a la propiedad values.

        self.combo["values"] = ["Python", "C", "C++", "Java"]

Un combobox en Tk trabaja únicamente con cadenas. Cualquier otro tipo de objeto será convertido antes de ser añadido a la lista.

La función Combobox.get retorna la opción seleccionada o bien escrita manualmente por el usuario (no hay distinción en ese sentido).

value = self.combo.get()

Siempre retorna una cadena y, en caso de no haber ninguna selección, devuelve una cadena vacía.

También es posible obtener el índice (es decir, su posición en la lista comenzando desde el 0) del elemento seleccionado vía Combobox.current().

index = self.combo.current()

Si no hay ningún elemento seleccionado o bien no se encuentra entre las opciones provistas (ha sido ingresado por el usuario) el valor de retorno es -1.

Análogamente, Combobox.set() establece el contenido de la lista.

self.combo.set("Python")

Y para seleccionar un elemento según su posición:

# Selecciona "C++".
self.combo.current(2)

Para obtener todas las opciones de la lista:

# Retorna ('Python', 'C', 'C++', 'Java')
values = self.combo["values"]

Nótese que retorna una tupla, no una lista. Para añadir una opción sin reemplazar a las demás, utilícese:

values = list(self.combo["values"])
self.combo["values"] = values + ["Nuevo elemento"]

Para remover todas las opciones, simplemente:

# Vaciar lista.
self.combo["values"] = []

ttk.Combobox introduce un nuevo evento llamado <<ComboboxSelected>> que es enviado cuando cambia la opción seleccionada.

    def __init__(self, main_window):
        super().__init__(main_window)
        main_window.title("Combobox")
        
        self.combo = ttk.Combobox(self)
        self.combo.place(x=50, y=50)
        self.combo["values"] = ["Python", "C", "C++", "Java"]
        self.combo.bind("<<ComboboxSelected>>", self.selection_changed)
        
        main_window.configure(width=300, height=200)
        self.place(width=300, height=200)
    
    def selection_changed(self, event):
        print("Nuevo elemento seleccionado:", self.combo.get())

Nótese que este evento no registra cambios introducidos manualmente por el usuario.

Para saber cuándo se ha abierto la lista (esto es, presionado en la flecha en el extremo derecho), en lugar de un evento simplemente se pasa una función al parámetro postcommand.

    def __init__(self, main_window):
        # ...
        self.combo = ttk.Combobox(self, postcommand=self.dropdown_opened)
        # ...
    
    def dropdown_opened(self):
        print("Lista desplegada.")



3 comentarios.

  1. Jorge Luis Silva Ojeda says:

    Muy buena información.

    Solo tengo una duda, si quiero poner 2 listas desplegables, pero que la 2da lista dé resultados diferentes dependiendo de la opción que se dio en la 1ra, (algo así como escoger el país y que en la siguiente te dé una lista de los estados) ¿qué debería agregar?

    De antemano, gracias!

    • Recursos Python says:

      Hola. En ese caso deberías asociar el evento <<ComboboxSelected>> de la primera lista para que al seleccionar una opción se carguen los elementos de la segunda.

      Saludos

Deja un comentario