martes, 24 de mayo de 2022

¿Cómo incorporar un Gráfico de Matplotlib en Tkinter y Guizero?


ventana de tkinter con gráfico insertado

¿Cómo incorporar un Gráfico de Matplotlib en Tkinter y Guizero?

A veces necesitamos incorporar gráficos de Matplotlib dentro de nuestras aplicaciones. Se puede enfocar este tema desde dos vertientes. (Lo primero no obstante es instalar esta librería, claro está.)

La primera es hacer un gráfico con la librería  Matplotlib, por ejemplo, guardarlo en un archivo en el mismo directorio y como hemos visto en un tema anterior cargarlo como cualquier otro gráfico en un widget.

Por ejemplo podemos construir un gráfico como el que se muestra a continuación utilizando la librería Matplotlib y guardándolo con la instrucción savefig() de esta librería. Puedes encontrar más información sobre como elaborar un gráfico en el siguiente enlace.

gráfico a insertar en una aplicación.


Y luego, una vez que tenemos el archivo lo podemos usar en nuestra GUI. En Guizero esto se realizaría usando PICTURE(). Matizar que Guizero solo permite usar imágenes en formato GIF o PNG.

El código puede ser parecido a este:

from guizero import *
'''Una forma de insertar un grafico es construyendolo con matplotlib,
guardandolo con la instrucion savefig()
y luego importarlo en guizero con Picture()'''

raiz=App()
Picture(raiz, image="grafico1.png", width=500, height=500)
raiz.display()

Lo que nos crea esta ventana con el gráfico dentro.

Gráfico insertado en una ventana


Código de esta aplicación en Github.


La segunda opción es incrustar ese gráfico en el widget directamente, aunque también es algo más compleja.

Podemos usar por ejemplo  este código que ya utilizamos en el capítulo de matplotlib para crear un simple gráfico de barras y trataremos de insertarlo en un widget.

import matplotlib.pyplot as plt
mascotas = [12, 9, 3, 1]
nombres = ["perros", "gatos", "peces", "tortugas"]
plt.bar(nombres, mascotas)
plt.plot()
plt.show()

Daría lugar al siguiente gráfico:

gráfico generado con matplotlib


Comenzamos importando las librerías que vamos a necesitar para crear una ventana y luego dibujar dentro el gráfico anterior.

# librerías de gráficos normales
import tkinter as tk
# librerías para insertar el gráfico
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# Librería para crear el gráfico
import matplotlib.pyplot as plt

Luego programamos la ventana de la aplicación y un contenedor tipo "frame" que será el que aloje el gráfico. 

# Creamos la ventana y el contenedor "frame" que contendrá el gráfico.
ventana = tk.Tk()
ventana.geometry('300x250')
ventana.title("Gráfica insertada en tkinter")
frame = tk.Frame(ventana, bg='yellow')
frame.grid(column=0, row=0, sticky='nsew')

Usando las listas con los datos que tenemos que son el nombre de las mascotas y su número o frecuencia procedemos a crear un gráfico.

mascotas = [12, 9, 3, 1]
nombres = ["perros", "gatos", "peces", "tortugas"]

fig, axs = plt.subplots(dpi=80, figsize=(4, 3))
fig.suptitle("Grafico Principal")

axs.bar(nombres, mascotas)

En este ejemplo creamos una figura que solamente tendrá un gráfico principal, es por ello que usamos la función fig, axs = plt.subplots().  Con dpi y figsize establecemos el tamaño del gráfico. También le añadimos un título y finalmente al ser solamente un gráfico usamos axs y el tipo de gráfico a crear, que en este caso es un gráfico de barras. 

Si queremos dibujar varios gráficos, habría que definirlos dentro de plt.subplots() y accederíamos a ellos con axs[0], ax[1] etc.

La novedad es que vamos a usar FigureCanvasTkAgg para dibujar el gráfico (fig) dentro del frame anteriormente definido, usando un canvas de tkinter:

# Dibujamos el gráfico dentro del frame definido usando
# un Canvas de tkinter.
canvas = FigureCanvasTkAgg(fig, master=frame)
canvas.draw()
canvas.get_tk_widget().grid(column=0, row=0)

ventana.mainloop()

Si todo ha ido bien el resultado será algo parecido a esto:

ventana de tkinter con gráfico insertado


Puedes encontrar el código en el siguiente enlace.



No hay comentarios:

Publicar un comentario