Introducción
En este laboratorio, aprenderá a crear un menú simple utilizando Matplotlib. El menú contendrá una lista de elementos, cada uno de los cuales puede ser seleccionado por el usuario. El elemento seleccionado entonces desencadenará una función de devolución de llamada que realizará alguna acción.
Consejos sobre la VM
Una vez finalizada la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.
A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de operaciones no puede automatizarse debido a las limitaciones de Jupyter Notebook.
Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje sus comentarios después de la sesión y lo resolveremos rápidamente para usted.
Importar bibliotecas
Para comenzar, necesitamos importar las bibliotecas necesarias. En este caso, necesitamos importar matplotlib.pyplot, matplotlib.artist, matplotlib.patches e IdentityTransform de matplotlib.transforms.
import matplotlib.pyplot as plt
import matplotlib.artist as artist
import matplotlib.patches as patches
from matplotlib.transforms import IdentityTransform
Definir la clase ItemProperties
A continuación, definimos una clase ItemProperties que se utilizará para establecer las propiedades de cada elemento del menú. Podemos establecer el tamaño de fuente, el color de la etiqueta, el color de fondo y el valor alfa para cada elemento utilizando esta clase.
class ItemProperties:
def __init__(self, fontsize=14, labelcolor='black', bgcolor='yellow',
alpha=1.0):
self.fontsize = fontsize
self.labelcolor = labelcolor
self.bgcolor = bgcolor
self.alpha = alpha
Definir la clase MenuItem
Ahora definimos una clase MenuItem que se utilizará para crear cada elemento del menú. Pasamos la figura, la cadena de etiqueta, las propiedades, las propiedades al pasar el cursor y la función de devolución de llamada al seleccionar como parámetros a esta clase. La clase MenuItem hereda de la clase artist.Artist.
class MenuItem(artist.Artist):
padx = 5
pady = 5
def __init__(self, fig, labelstr, props=None, hoverprops=None,
on_select=None):
super().__init__()
self.set_figure(fig)
self.labelstr = labelstr
self.props = props if props is not None else ItemProperties()
self.hoverprops = (
hoverprops if hoverprops is not None else ItemProperties())
if self.props.fontsize!= self.hoverprops.fontsize:
raise NotImplementedError(
'support for different font sizes not implemented')
self.on_select = on_select
## Setting the transform to IdentityTransform() lets us specify
## coordinates directly in pixels.
self.label = fig.text(0, 0, labelstr, transform=IdentityTransform(),
size=props.fontsize)
self.text_bbox = self.label.get_window_extent(
fig.canvas.get_renderer())
self.rect = patches.Rectangle((0, 0), 1, 1) ## Will be updated later.
self.set_hover_props(False)
fig.canvas.mpl_connect('button_release_event', self.check_select)
def check_select(self, event):
over, _ = self.rect.contains(event)
if not over:
return
if self.on_select is not None:
self.on_select(self)
def set_extent(self, x, y, w, h, depth):
self.rect.set(x=x, y=y, width=w, height=h)
self.label.set(position=(x + self.padx, y + depth + self.pady/2))
self.hover = False
def draw(self, renderer):
self.rect.draw(renderer)
self.label.draw(renderer)
def set_hover_props(self, b):
props = self.hoverprops if b else self.props
self.label.set(color=props.labelcolor)
self.rect.set(facecolor=props.bgcolor, alpha=props.alpha)
def set_hover(self, event):
"""
Update the hover status of event and return whether it was changed.
"""
b, _ = self.rect.contains(event)
changed = (b!= self.hover)
if changed:
self.set_hover_props(b)
self.hover = b
return changed
Definir la clase Menu
También necesitamos definir una clase Menu que se utilizará para crear el menú. Pasamos la figura y la lista de elementos del menú como parámetros a esta clase.
class Menu:
def __init__(self, fig, menuitems):
self.figure = fig
self.menuitems = menuitems
maxw = max(item.text_bbox.width for item in menuitems)
maxh = max(item.text_bbox.height for item in menuitems)
depth = max(-item.text_bbox.y0 for item in menuitems)
x0 = 100
y0 = 400
width = maxw + 2*MenuItem.padx
height = maxh + MenuItem.pady
for item in menuitems:
left = x0
bottom = y0 - maxh - MenuItem.pady
item.set_extent(left, bottom, width, height, depth)
fig.artists.append(item)
y0 -= maxh + MenuItem.pady
fig.canvas.mpl_connect('motion_notify_event', self.on_move)
def on_move(self, event):
if any(item.set_hover(event) for item in self.menuitems):
self.figure.canvas.draw()
Crear el menú
Ahora podemos crear el menú. Creamos una nueva figura y ajustamos el margen izquierdo. Luego creamos una lista de elementos del menú y los agregamos al menú. También definimos una función de devolución de llamada para cada elemento que imprimirá el elemento seleccionado.
fig = plt.figure()
fig.subplots_adjust(left=0.3)
props = ItemProperties(labelcolor='black', bgcolor='yellow',
fontsize=15, alpha=0.2)
hoverprops = ItemProperties(labelcolor='white', bgcolor='blue',
fontsize=15, alpha=0.2)
menuitems = []
for label in ('open', 'close','save','save as', 'quit'):
def on_select(item):
print('you selected %s' % item.labelstr)
item = MenuItem(fig, label, props=props, hoverprops=hoverprops,
on_select=on_select)
menuitems.append(item)
menu = Menu(fig, menuitems)
plt.show()
Resumen
¡Felicidades! Has creado con éxito un menú simple utilizando Matplotlib. Has aprendido cómo crear una clase MenuItem, una clase Menu y cómo definir propiedades para cada elemento. También has aprendido cómo crear una función de devolución de llamada para cada elemento que realizará alguna acción.