路径编辑器

跨GUI共享事件。

此示例演示了使用Matplotlib事件处理与画布上的对象进行交互和修改对象的跨GUI应用程序。

路径编辑器示例

  1. import numpy as np
  2. import matplotlib.path as mpath
  3. import matplotlib.patches as mpatches
  4. import matplotlib.pyplot as plt
  5. Path = mpath.Path
  6. fig, ax = plt.subplots()
  7. pathdata = [
  8. (Path.MOVETO, (1.58, -2.57)),
  9. (Path.CURVE4, (0.35, -1.1)),
  10. (Path.CURVE4, (-1.75, 2.0)),
  11. (Path.CURVE4, (0.375, 2.0)),
  12. (Path.LINETO, (0.85, 1.15)),
  13. (Path.CURVE4, (2.2, 3.2)),
  14. (Path.CURVE4, (3, 0.05)),
  15. (Path.CURVE4, (2.0, -0.5)),
  16. (Path.CLOSEPOLY, (1.58, -2.57)),
  17. ]
  18. codes, verts = zip(*pathdata)
  19. path = mpath.Path(verts, codes)
  20. patch = mpatches.PathPatch(path, facecolor='green', edgecolor='yellow', alpha=0.5)
  21. ax.add_patch(patch)
  22. class PathInteractor(object):
  23. """
  24. An path editor.
  25. Key-bindings
  26. 't' toggle vertex markers on and off. When vertex markers are on,
  27. you can move them, delete them
  28. """
  29. showverts = True
  30. epsilon = 5 # max pixel distance to count as a vertex hit
  31. def __init__(self, pathpatch):
  32. self.ax = pathpatch.axes
  33. canvas = self.ax.figure.canvas
  34. self.pathpatch = pathpatch
  35. self.pathpatch.set_animated(True)
  36. x, y = zip(*self.pathpatch.get_path().vertices)
  37. self.line, = ax.plot(x, y, marker='o', markerfacecolor='r', animated=True)
  38. self._ind = None # the active vert
  39. canvas.mpl_connect('draw_event', self.draw_callback)
  40. canvas.mpl_connect('button_press_event', self.button_press_callback)
  41. canvas.mpl_connect('key_press_event', self.key_press_callback)
  42. canvas.mpl_connect('button_release_event', self.button_release_callback)
  43. canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
  44. self.canvas = canvas
  45. def draw_callback(self, event):
  46. self.background = self.canvas.copy_from_bbox(self.ax.bbox)
  47. self.ax.draw_artist(self.pathpatch)
  48. self.ax.draw_artist(self.line)
  49. self.canvas.blit(self.ax.bbox)
  50. def pathpatch_changed(self, pathpatch):
  51. 'this method is called whenever the pathpatchgon object is called'
  52. # only copy the artist props to the line (except visibility)
  53. vis = self.line.get_visible()
  54. plt.Artist.update_from(self.line, pathpatch)
  55. self.line.set_visible(vis) # don't use the pathpatch visibility state
  56. def get_ind_under_point(self, event):
  57. 'get the index of the vertex under point if within epsilon tolerance'
  58. # display coords
  59. xy = np.asarray(self.pathpatch.get_path().vertices)
  60. xyt = self.pathpatch.get_transform().transform(xy)
  61. xt, yt = xyt[:, 0], xyt[:, 1]
  62. d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
  63. ind = d.argmin()
  64. if d[ind] >= self.epsilon:
  65. ind = None
  66. return ind
  67. def button_press_callback(self, event):
  68. 'whenever a mouse button is pressed'
  69. if not self.showverts:
  70. return
  71. if event.inaxes is None:
  72. return
  73. if event.button != 1:
  74. return
  75. self._ind = self.get_ind_under_point(event)
  76. def button_release_callback(self, event):
  77. 'whenever a mouse button is released'
  78. if not self.showverts:
  79. return
  80. if event.button != 1:
  81. return
  82. self._ind = None
  83. def key_press_callback(self, event):
  84. 'whenever a key is pressed'
  85. if not event.inaxes:
  86. return
  87. if event.key == 't':
  88. self.showverts = not self.showverts
  89. self.line.set_visible(self.showverts)
  90. if not self.showverts:
  91. self._ind = None
  92. self.canvas.draw()
  93. def motion_notify_callback(self, event):
  94. 'on mouse movement'
  95. if not self.showverts:
  96. return
  97. if self._ind is None:
  98. return
  99. if event.inaxes is None:
  100. return
  101. if event.button != 1:
  102. return
  103. x, y = event.xdata, event.ydata
  104. vertices = self.pathpatch.get_path().vertices
  105. vertices[self._ind] = x, y
  106. self.line.set_data(zip(*vertices))
  107. self.canvas.restore_region(self.background)
  108. self.ax.draw_artist(self.pathpatch)
  109. self.ax.draw_artist(self.line)
  110. self.canvas.blit(self.ax.bbox)
  111. interactor = PathInteractor(patch)
  112. ax.set_title('drag vertices to update path')
  113. ax.set_xlim(-3, 4)
  114. ax.set_ylim(-3, 4)
  115. plt.show()

下载这个示例