Crear un menú simple con Matplotlib

PythonPythonBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

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

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

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.