Widgets esenciales en Tkinter: Label, Button y Entry
En esta guía paso‑a‑paso descubrirás cómo crear, personalizar y gestionar los tres widgets más usados en aplicaciones de escritorio con Tkinter, el toolkit estándar de Python.
1. ¿Por qué estos tres widgets?
Un Label muestra información estática, un Button permite al usuario disparar acciones y un Entry captura texto de entrada. Juntos forman la base de cualquier interfaz: presentación, interacción y recolección de datos.
Características clave
- Label: texto, imágenes, alineación,
wraplength,justify. - Button: comandos,
state(normal/disabled), imágenes,bindpara eventos extra. - Entry: captura de texto, validación en tiempo real,
showpara contraseñas,maxlengthmediantevalidate.
Ventajas frente a alternativas
| Widget | Tkinter | Qt (PySide) | WxPython |
|---|---|---|---|
| Label | Ligero, sin dependencias externas | Más capacidad de estilos CSS‑like | Soporta HTML limitado |
| Button | Simple, fácil de enlazar con funciones | Signal‑Slot avanzado | Eventos personalizados |
| Entry | Validación con validatecommand | QLineEdit con máscaras | TextCtrl con estilos |
2. Creando un Label con texto personalizado
El widget Label muestra texto o imágenes. Puedes definir fuente, color de fondo, color de texto y alineación.
import tkinter as tk
from tkinter import font
root = tk.Tk()
root.title("Ejemplo de Label")
# Fuente personalizada
mi_fuente = font.Font(family="Helvetica", size=14, weight="bold")
lbl = tk.Label(
root,
text="¡Hola, Tkinter!",
font=mi_fuente,
fg="#ffffff", # color del texto
bg="#007acc", # color de fondo
padx=10, pady=5,
relief="groove"
)
lbl.pack(pady=20)
root.mainloop()
Consejo de seguridad: nunca inserte texto sin escaparlo si proviene de usuarios externos; use html.escape antes de asignarlo a un Label que muestre HTML (cuando se usa tkinterhtml).
3. Un Button que ejecuta una función al hacer clic
Los botones pueden estar vinculados a cualquier función Python mediante el parámetro command. También puedes usar bind para capturar eventos como <Enter> o <Double-Button-1>.
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.title("Botón con acción")
def saludar():
nombre = entry_nombre.get()
if not nombre:
messagebox.showwarning("Entrada vacía", "Escribe tu nombre antes de saludar.")
return
messagebox.showinfo("Saludo", f"¡Hola, {nombre}!")
# Entrada para capturar el nombre (ver sección 4)
entry_nombre = tk.Entry(root, width=30)
entry_nombre.pack(pady=10)
btn = tk.Button(
root,
text="Saludar",
command=saludar,
bg="#28a745",
fg="#ffffff",
activebackground="#218838",
font=("Arial", 12, "bold"),
padx=12, pady=6,
cursor="hand2"
)
btn.pack(pady=5)
root.mainloop()
Mejores prácticas: siempre usa command=función sin paréntesis. Si necesitas pasar argumentos, usa lambda o functools.partial para evitar la ejecución inmediata.
4. Capturando texto con Entry y validación en tiempo real
El widget Entry permite al usuario introducir una cadena. Con la opción validate='key' y una función de validación puedes restringir la entrada (por ejemplo, solo números).
import tkinter as tk
root = tk.Tk()
root.title("Entry con validación")
def validar_numeros(P):
"""Devuelve True si P es cadena vacía o solo contiene dígitos"""
return P.isdigit() or P == ""
vcmd = (root.register(validar_numeros), "%P")
entry_num = tk.Entry(
root,
validate="key",
validatecommand=vcmd,
font=("Consolas", 12),
width=20,
bg="#f8f9fa",
fg="#212529"
)
entry_num.pack(pady=15)
lbl_res = tk.Label(root, text="Introduce solo números", font=("Helvetica", 10))
lbl_res.pack()
root.mainloop()
En la función de validación, %P representa el contenido propuesto del Entry. Si la función devuelve False, la tecla es ignorada.
Depuración: si la validación no funciona, verifica que root.register() se haya llamado antes de crear el widget y que la tupla (func, "%P") sea la que se pasa a validatecommand.
5. Personalización avanzada con ttk (Themed Tk)
Para interfaces más modernas, usa ttk que soporta temas y estilos CSS‑like. A continuación, un mini‑ejemplo que aplica un tema oscuro y modifica la apariencia de Button y Entry:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("Tema oscuro con ttk")
style = ttk.Style()
style.theme_use('clam') # Cambia a un tema base modificable
# Definir colores
bg = "#2d2d2d"
fg = "#f0f0f0"
style.configure('TLabel', background=bg, foreground=fg, font=('Segoe UI', 11))
style.configure('TButton', background="#4a90e2", foreground=fg, font=('Segoe UI', 10, 'bold'))
style.map('TButton', background=[('active', '#357ab8')])
style.configure('TEntry', fieldbackground="#3c3c3c", foreground=fg, font=('Consolas', 10))
root.configure(background=bg)
lbl = ttk.Label(root, text="Etiqueta con tema oscuro")
lbl.pack(pady=10)
entry = ttk.Entry(root, width=30)
entry.pack(pady=5)
btn = ttk.Button(root, text="Aceptar")
btn.pack(pady=10)
root.mainloop()
Usar ttk permite cambiar la apariencia sin tocar cada widget individualmente, lo que mejora la mantenibilidad y la consistencia visual.
6. Buenas prácticas y trucos de troubleshooting
- Separar lógica y UI: coloca la lógica de negocio en funciones o clases separadas; los callbacks de los botones deben ser ligeros y delegar a esas capas.
- Gestión de geometría: usa
gridpara formularios ypackpara disposiciones simples. Evita mezclar ambos en el mismo contenedor. - Escalado en alta DPI: llama a
root.tk.call('tk', 'scaling', factor)para ajustar el factor de escala en pantallas Retina. - Depuración de eventos: imprime
event.typeyevent.widgetdentro de una funciónbindpara entender el flujo. - Seguridad de datos sensibles: si usas
Entrypara contraseñas, defineshow='*'y nunca guardes la cadena en texto plano; utilizakeyringo hashing.