Dibujando en la pantalla: el widget Canvas de Tkinter
Todo lo que necesitas saber para crear dibujos, diagramas, juegos simples y una mini‑aplicación tipo Paint con Tkinter.
¿Qué es el Canvas y para qué se usa?
El Canvas es el único widget de Tkinter que permite dibujar gráficos vectoriales directamente sobre una superficie pixel‑based. Sus principales casos de uso son:
- Juegos 2D sencillos (p. ej., Snake, Pong).
- Diagramas interactivos (flujos, árboles, mapas de sitio).
- Gráficos estadísticos o de ingeniería (barras, líneas, dispersión).
- Herramientas de edición manual, como un paint básico.
Sistema de coordenadas
El origen ((0,0)) está en la esquina superior‑izquierda del Canvas. El eje x crece hacia la derecha y el eje y hacia abajo. Cada unidad corresponde a un pixel, aunque se pueden aplicar transformaciones de escala para coordenadas lógicas.
Ejemplo rápido:
canvas.create_line(0, 0, 100, 50) # Línea de (0,0) a (100,50)
Dibujando primitivas básicas
Líneas y polígonos
canvas.create_line(10, 10, 200, 10, fill="#ff5733", width=3)
canvas.create_polygon(50,60, 150,60, 100,120, outline="black", fill="#88c0d0", width=2)
Rectángulos y óvalos
# rectángulo (x1,y1,x2,y2)
canvas.create_rectangle(20, 150, 180, 250, outline="green", fill="#a3be8c", width=2)
# óvalo (encierra un rectángulo)
canvas.create_oval(220, 150, 320, 250, outline="purple", fill="#b48ead", width=2)
Texto e imágenes
Texto
canvas.create_text(150, 300, text="Hola, Canvas!", font=("Helvetica", 16, "bold"), fill="#5e81ac")
Imágenes
Tkinter necesita objetos PhotoImage o PIL.ImageTk.PhotoImage (para PNG/JPG).
from tkinter import PhotoImage
img = PhotoImage(file="icon.png")
canvas.create_image(300, 300, image=img, anchor="center")
# Nota: mantener una referencia a 'img' para evitar que sea recolectado.
Ejemplo práctico: Mini‑Paint con Tkinter
Una aplicación mínima que permite dibujar con el ratón, cambiar color y grosor.
import tkinter as tk
from tkinter import colorchooser
class SimplePaint(tk.Tk):
def __init__(self):
super().__init__()
self.title("Simple Paint – Tkinter Canvas")
self.geometry("800x600")
self.current_color = "#000000"
self.brush_size = 3
# Toolbar
toolbar = tk.Frame(self, bg="#eceff4")
toolbar.pack(side="top", fill="x")
tk.Button(toolbar, text="Color", command=self.choose_color).pack(side="left", padx=5, pady=5)
tk.Scale(toolbar, from_=1, to=10, orient="horizontal", label="Grosor",
command=self.change_size).pack(side="left", padx=5)
# Canvas
self.canvas = tk.Canvas(self, bg="white", cursor="cross")
self.canvas.pack(fill="both", expand=True)
self.canvas.bind("", self.on_button_press)
self.canvas.bind("", self.on_move)
self.last_x, self.last_y = None, None
def choose_color(self):
color = colorchooser.askcolor(initialcolor=self.current_color)[1]
if color:
self.current_color = color
def change_size(self, val):
self.brush_size = int(val)
def on_button_press(self, event):
self.last_x, self.last_y = event.x, event.y
def on_move(self, event):
x, y = event.x, event.y
self.canvas.create_line(self.last_x, self.last_y, x, y,
fill=self.current_color,
width=self.brush_size,
capstyle=tk.ROUND,
smooth=True)
self.last_x, self.last_y = x, y
if __name__ == "__main__":
SimplePaint().mainloop()
Este código muestra los conceptos clave: manejo de eventos (<ButtonPress-1>, <B1-Motion>), uso de create_line con suavizado y cómo conectar una barra de herramientas sencilla.
Canvas vs. alternativas modernas
Tkinter Canvas
- Incluido en la librería estándar de Python (sin dependencias).
- Ideal para prototipos rápidos y herramientas internas.
- Rendimiento suficiente para < 10 000 objetos visibles.
- Limitado a 2D; no soporta aceleración GPU.
Qt (QGraphicsView) / PySide6
- Renderizado con OpenGL opcional → mejor rendimiento en escenas complejas.
- Mayor soporte para objetos interactivos y transformaciones.
- Curva de aprendizaje más alta y dependencia externa.
- Licencia LGPL/Commercial.
Mejores prácticas, rendimiento y troubleshooting
1️⃣ Minimiza la cantidad de objetos
Demasiados ítems (< 20 000) pueden ralentizar la actualización. Usa create_line con varios puntos o dibuja en una PhotoImage cuando necesites trazos continuos masivos.
2️⃣ Mantén referencias a imágenes
Tkinter elimina imágenes sin referencia explícita, provocando blank canvas. Guarda la imagen en una lista o como atributo del widget.
3️⃣ Gestiona eventos correctamente
Evita crear nuevos objetos dentro de <Motion> sin control de frecuencia; usa after_idle o throttling para limitar a ~60 fps.
4️⃣ Seguridad y sandbox
Cuando cargues imágenes de fuentes externas, valida extensiones y tamaños para prevenir Denial‑of‑Service por archivos enormes.
5️⃣ Compatibilidad
Funciona en Windows, macOS y la mayoría de distribuciones Linux con Tk 8.6+. En macOS, habilita --enable-high-dpi para que el canvas se escale correctamente en pantallas Retina.
Conclusión
El widget Canvas de Tkinter sigue siendo una herramienta poderosa y ligera para crear interfaces gráficas interactivas en Python. Conociendo su sistema de coordenadas, los métodos de dibujo y aplicando buenas prácticas, puedes desarrollar desde diagramas simples hasta mini‑juegos y editores de dibujo sin depender de librerías externas.
14 Dibujando en la pantalla: el widget Canvas de Tkinter