WhatsApp

  

15 Trabajando con imágenes en Tkinter: logos, fondos y botones

Guía completa para cargar y mostrar imágenes en Tkinter usando PhotoImage y Pillow, con ejemplos para Label, Button y Canvas, y buenas prácticas para evitar que desaparezcan.

Trabajando con imágenes en Tkinter: logos, fondos y botones

Aprende a cargar imágenes en tus interfaces gráficas con Tkinter, descubre las limitaciones de PhotoImage, cómo superarlas con Pillow (PIL) y evita el temido error de que la imagen desaparezca.

1. ¿Qué formatos soporta PhotoImage por defecto?

El widget PhotoImage incorporado en Tkinter está limitado a los siguientes formatos sin dependencias externas:

  • GIF (animado y estático)
  • PPM/PGM (formato de mapa de bits propio de Tk)
  • PNG (desde Python 3.4, pero solo versiones sin transparencia avanzada)

Si necesitas trabajar con JPG, BMP, TIFF o PNG con canales alfa complejos, deberás recurrir a Pillow.

2. Pillow (PIL) como puente para formatos modernos

Pillow es una bifurcación mantenida de la antigua biblioteca PIL. Con ella puedes cargar prácticamente cualquier formato de imagen y convertirlo a un objeto PhotoImage que Tkinter entienda.

# Instalación
pip install pillow
# Conversión de una imagen JPG a PhotoImage
from PIL import Image, ImageTk
pil_img = Image.open('foto.jpg')          # Carga JPG, PNG, BMP, etc.
tk_img   = ImageTk.PhotoImage(pil_img)   # Convierte a PhotoImage usable por Tkinter

Ventajas de usar Pillow:

  • Soporte nativo para JPG, PNG (con alfa), BMP, ICO, WebP, TIFF.
  • Herramientas de resize, crop, rotate y filter integradas.
  • Compatibilidad con Python 3.8‑3.12 y todas las plataformas principales.

3. Añadir imágenes a los widgets de Tkinter

A continuación, ejemplos funcionales para Label, Button y Canvas. Cada bloque muestra dos versiones: usando solo PhotoImage (para GIF/PNG) y usando Pillow (para JPG/PNG avanzado).

3.1. Label con PhotoImage

import tkinter as tk
root = tk.Tk()
logo = tk.PhotoImage(file='logo.gif')   # GIF o PNG simple
lbl  = tk.Label(root, image=logo)
lbl.pack()
root.mainloop()

Nota: Mantén la referencia logo fuera del ámbito del widget.

3.2. Label con Pillow (JPG/PNG con alfa)

import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
pil_img = Image.open('foto.jpg')
photo   = ImageTk.PhotoImage(pil_img)
lbl     = tk.Label(root, image=photo)
lbl.pack()
root.mainloop()

3.3. Button con PhotoImage

import tkinter as tk
root = tk.Tk()
icon = tk.PhotoImage(file='icon.png')
btn  = tk.Button(root, image=icon, command=lambda: print('¡clic!'))
btn.pack(pady=10)
root.mainloop()

3.4. Button con Pillow (PNG con transparencia)

import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
pil_icon = Image.open('icon_transparent.png')
icon     = ImageTk.PhotoImage(pil_icon)
btn      = tk.Button(root, image=icon, command=lambda: print('¡clic!'))
btn.pack(pady=10)
root.mainloop()

3.5. Canvas con PhotoImage (fondo y sprites)

import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=300)
canvas.pack()
bg   = tk.PhotoImage(file='fondo.png')
sprite = tk.PhotoImage(file='sprite.gif')
canvas.create_image(0, 0, anchor='nw', image=bg)      # Fondo
canvas.create_image(200, 150, image=sprite)          # Sprite central
root.mainloop()

Si el fondo es JPG, usa Pillow para cargarlo y conviértelo a PhotoImage antes de pasar a create_image.

4. El temido problema de la desaparición de la imagen

Tkinter gestiona la vida de los objetos PhotoImage mediante referencia de Python. Si la única referencia está dentro del widget y no se guarda en una variable, el recolector de basura los elimina y la GUI queda sin la imagen.

# Código erróneo (la imagen desaparece al actualizar la ventana)
import tkinter as tk
root = tk.Tk()
btn = tk.Button(root, image=tk.PhotoImage(file='icon.png'))
btn.pack()
root.mainloop()

Solución: asigna la imagen a una variable de alcance global o como atributo del widget.

# Solución correcta
import tkinter as tk
root = tk.Tk()
icon = tk.PhotoImage(file='icon.png')
btn  = tk.Button(root, image=icon)
btn.image = icon          # atributo para mantener referencia
btn.pack()
root.mainloop()

En aplicaciones más grandes, es una buena práctica almacenar todas las imágenes en un diccionario centralizado (self.images = {}) dentro de la clase principal.

5. Buenas prácticas y trucos avanzados

  • Escalado inteligente: usa Image.thumbnail() o Image.resize() antes de crear el PhotoImage para reducir consumo de memoria.
  • Gestión de recursos: cierra los archivos con pil_img.close() cuando ya no los necesites.
  • Cache de imágenes: en interfaces con muchos iconos, crea una caché (p.ej., self.icon_cache = {}) para evitar cargar el mismo archivo repetidamente.
  • Compatibilidad multiplataforma: verifica que los caminos de archivo usen os.path.join y Pathlib para evitar problemas en Windows vs Linux.
  • Rendimiento: en animaciones, pre‑carga todos los fotogramas como objetos PhotoImage y actualiza el widget con config(image=frame) en un after() loop.

© 2025 Tu Blog de Python – Todos los derechos reservados.

 

15 Trabajando con imágenes en Tkinter: logos, fondos y botones
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 10 diciembre, 2025
Compartir
Iniciar sesión dejar un comentario

  
14 Dibujando en la pantalla: el widget Canvas de Tkinter
Guía completa y práctica sobre el widget Canvas de Tkinter: conceptos, coordenadas, dibujo de formas, texto e imágenes, y una mini‑aplicación Paint. Incluye buenas prácticas, trucos de rendimiento y comparativas con otras librerías gráficas.