Lección 2 · 2 de 20
Un gráfico de barras · tkinter
Dibuje un gráfico de barras en un Canvas de tkinter a partir de un diccionario de datos: escala, rejilla, ejes y etiquetas.

Los datos están en un diccionario, sales: cada mes con sus unidades vendidas. El gráfico no se dibuja a mano: el bucle lo construye a partir de los datos, así que si cambia un número, cambia la barra.
La clave es escalar: y_of(value) convierte un valor (de 0 a MAX) en una coordenada y entre BOTTOM y TOP. Como la y del lienzo crece hacia abajo, se resta: el 0 queda abajo y el 100, arriba. Cada barra tiene un hueco de ancho step (el ancho útil entre el número de meses) y se le quitan 12 píxeles por cada lado para separarlas.
Primero se dibuja el fondo: la rejilla cada 25 unidades, con su valor a la izquierda (anchor="e" alinea el texto por la derecha), y el eje x. Después, cada barra con create_rectangle (width=0: sin borde), su valor encima y el mes debajo. Lo que se dibuja después queda encima.
max(sales, key=sales.get) busca el mes con más ventas, y su barra sale en verde. La etiqueta ttk.Label de abajo suma el total con sum(sales.values()).
En DMarlon Studio no hace falta dibujarlo: el componente Gráfico de la paleta dibuja líneas, áreas, barras o velas, con el título, los ejes, la leyenda y la rejilla que elija en el inspector, y el estudio escribe el código de tkinter. Esta lección enseña lo que hay debajo: un lienzo y un poco de aritmética.
Código · main.py
import tkinter as tkfrom tkinter import ttksales = {"Jan": 42, "Feb": 58, "Mar": 35, "Apr": 71, "May": 64, "Jun": 88}root = tk.Tk()root.title("Monthly sales")root.geometry("560x380")canvas = tk.Canvas(root, bg="white", highlightthickness=0, height=340)canvas.pack(fill="x")best = max(sales, key=sales.get)ttk.Label(root, text=f"Total: {sum(sales.values())} units · best month: {best}").pack(pady=8)W, LEFT, TOP, BOTTOM, MAX = 560, 50, 60, 310, 100step = (W - LEFT - 20) / len(sales) # room for each bardef y_of(value): # a value -> a y coordinate (0 at the bottom) return BOTTOM - value / MAX * (BOTTOM - TOP)canvas.create_text(W / 2, 26, text="Units sold per month", font=("Helvetica", 15, "bold"))for v in range(0, MAX + 1, 25): # grid lines with their values canvas.create_line(LEFT, y_of(v), W - 20, y_of(v), fill="#e5e5e5") canvas.create_text(LEFT - 8, y_of(v), text=v, anchor="e", fill="gray")canvas.create_line(LEFT, BOTTOM, W - 20, BOTTOM) # x axisfor i, (month, value) in enumerate(sales.items()): x0 = LEFT + i * step + 12 x1 = x0 + step - 24 color = "#2e9d5b" if month == best else "#4f8cf7" canvas.create_rectangle(x0, y_of(value), x1, BOTTOM, fill=color, width=0) canvas.create_text((x0 + x1) / 2, y_of(value) - 10, text=value) canvas.create_text((x0 + x1) / 2, BOTTOM + 14, text=month)root.mainloop()Para recordar
- Escalar es pasar de valores a píxeles con una regla de tres.
- La y crece hacia abajo: por eso se resta de
BOTTOM. - Lo que se dibuja después queda encima.
- El bucle dibuja lo que haya en los datos.
Ejercicio
Añada julio (95) y agosto (60) al diccionario y compruebe que las barras se reparten solas; después pinte de rojo las que no lleguen a 40.