.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/event_handling/path_editor.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. meta:: :keywords: codex .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_event_handling_path_editor.py: =========== Path editor =========== Sharing events across GUIs. This example demonstrates a cross-GUI application using Matplotlib event handling to interact with and modify objects on the canvas. .. note:: This example exercises the interactive capabilities of Matplotlib, and this will not appear in the static documentation. Please run this code on your machine to see the interactivity. You can copy and paste individual parts, or download the entire example using the link at the bottom of the page. .. GENERATED FROM PYTHON SOURCE LINES 19-150 .. image-sg:: /gallery/event_handling/images/sphx_glr_path_editor_001.png :alt: drag vertices to update path :srcset: /gallery/event_handling/images/sphx_glr_path_editor_001.png, /gallery/event_handling/images/sphx_glr_path_editor_001_2_00x.png 2.00x :class: sphx-glr-single-img .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from matplotlib.backend_bases import MouseButton from matplotlib.patches import PathPatch from matplotlib.path import Path fig, ax = plt.subplots() pathdata = [ (Path.MOVETO, (1.58, -2.57)), (Path.CURVE4, (0.35, -1.1)), (Path.CURVE4, (-1.75, 2.0)), (Path.CURVE4, (0.375, 2.0)), (Path.LINETO, (0.85, 1.15)), (Path.CURVE4, (2.2, 3.2)), (Path.CURVE4, (3, 0.05)), (Path.CURVE4, (2.0, -0.5)), (Path.CLOSEPOLY, (1.58, -2.57)), ] codes, verts = zip(*pathdata) path = Path(verts, codes) patch = PathPatch( path, facecolor='green', edgecolor='yellow', alpha=0.5) ax.add_patch(patch) class PathInteractor: """ A path editor. Press 't' to toggle vertex markers on and off. When vertex markers are on, they can be dragged with the mouse. """ showverts = True epsilon = 5 # max pixel distance to count as a vertex hit def __init__(self, pathpatch): self.ax = pathpatch.axes canvas = self.ax.figure.canvas self.pathpatch = pathpatch self.pathpatch.set_animated(True) x, y = zip(*self.pathpatch.get_path().vertices) self.line, = ax.plot( x, y, marker='o', markerfacecolor='r', animated=True) self._ind = None # the active vertex canvas.mpl_connect('draw_event', self.on_draw) canvas.mpl_connect('button_press_event', self.on_button_press) canvas.mpl_connect('key_press_event', self.on_key_press) canvas.mpl_connect('button_release_event', self.on_button_release) canvas.mpl_connect('motion_notify_event', self.on_mouse_move) self.canvas = canvas def get_ind_under_point(self, event): """ Return the index of the point closest to the event position or *None* if no point is within ``self.epsilon`` to the event position. """ xy = self.pathpatch.get_path().vertices xyt = self.pathpatch.get_transform().transform(xy) # to display coords xt, yt = xyt[:, 0], xyt[:, 1] d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2) ind = d.argmin() return ind if d[ind] < self.epsilon else None def on_draw(self, event): """Callback for draws.""" self.background = self.canvas.copy_from_bbox(self.ax.bbox) self.ax.draw_artist(self.pathpatch) self.ax.draw_artist(self.line) self.canvas.blit(self.ax.bbox) def on_button_press(self, event): """Callback for mouse button presses.""" if (event.inaxes is None or event.button != MouseButton.LEFT or not self.showverts): return self._ind = self.get_ind_under_point(event) def on_button_release(self, event): """Callback for mouse button releases.""" if (event.button != MouseButton.LEFT or not self.showverts): return self._ind = None def on_key_press(self, event): """Callback for key presses.""" if not event.inaxes: return if event.key == 't': self.showverts = not self.showverts self.line.set_visible(self.showverts) if not self.showverts: self._ind = None self.canvas.draw() def on_mouse_move(self, event): """Callback for mouse movements.""" if (self._ind is None or event.inaxes is None or event.button != MouseButton.LEFT or not self.showverts): return vertices = self.pathpatch.get_path().vertices vertices[self._ind] = event.xdata, event.ydata self.line.set_data(zip(*vertices)) self.canvas.restore_region(self.background) self.ax.draw_artist(self.pathpatch) self.ax.draw_artist(self.line) self.canvas.blit(self.ax.bbox) interactor = PathInteractor(patch) ax.set_title('drag vertices to update path') ax.set_xlim(-3, 4) ax.set_ylim(-3, 4) plt.show() .. _sphx_glr_download_gallery_event_handling_path_editor.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: path_editor.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: path_editor.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_