.. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_widgets_menu.py: ==== Menu ==== .. image:: /gallery/widgets/images/sphx_glr_menu_001.png :alt: menu :class: sphx-glr-single-img .. code-block:: default import matplotlib.artist as artist import matplotlib.patches as patches import matplotlib.pyplot as plt from matplotlib.transforms import IdentityTransform 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 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 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() 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() .. _sphx_glr_download_gallery_widgets_menu.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: menu.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: menu.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature Keywords: matplotlib code example, codex, python plot, pyplot `Gallery generated by Sphinx-Gallery `_