我有一个 python 程序,它创建一个 matplotlib 图形和添加到其中的许多矩形艺术家。每个艺术家都会安装一个通用的单击处理程序,当鼠标在矩形内单击时会调用该处理程序。问题是我不知道如何确定单击了哪个矩形。传递给处理程序的单击事件确实包括单击时鼠标的位置,但我必须测试每个矩形以查看哪个矩形包含该点。
必须有一种更简单的方法来做到这一点。
矩形可能已以各种方式添加到斧头:
ax.add_collection(patch_collection)
,那么event.artist
将是整个patch_collection
,但您可以使用event.ind
检索触发它的内部补丁的索引。ax.add_patch(rectangle)
,则 event.artist
将是单独触发的矩形。根据情况,您可能需要以不同的方式处理回调。
from itertools import product
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection
# Rectangles parameters
width = 1
height = 1
nrows = 5
ncols = 7
inbetween = 0.1
xx = np.arange(0, ncols, (width + inbetween))
yy = np.arange(0, nrows, (height + inbetween))
# Create two identical sets of rectangles (for 2 figures)
patches1 = []
patches2 = []
for xi, yi in product(xx, yy):
square1 = Rectangle((xi, yi), width, height, fill=True, picker=True)
square2 = Rectangle((xi, yi), width, height, fill=True, picker=True)
patches1.append(square1)
patches2.append(square2)
# Create figure
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4), subplot_kw=dict(aspect="equal"))
ax1.set_xlim(-1, ncols * (width + inbetween) + 1)
ax1.set_ylim(-1, nrows * (height + inbetween) + 1)
ax2.set_xlim(-1, ncols * (width + inbetween) + 1)
ax2.set_ylim(-1, nrows * (height + inbetween) + 1)
# Fig 1: PatchCollection
patch_collection = PatchCollection(patches1, picker=True)
ax1.add_collection(patch_collection)
ax1.set_title("PatchCollection")
# Fig 2: Individual patches
for patch in patches2:
ax2.add_patch(patch)
ax2.set_title("Individual patches")
# Callback
def on_pick(event):
mouseevent = event.mouseevent
artist = event.artist
print(artist)
if isinstance(artist, PatchCollection):
patch_idx = event.ind[0]
paths = artist.get_paths()
# path = paths[patch_idx]
facecolors = ["C0"] * len(paths)
facecolors[patch_idx] = "red"
# Need to set all facecolors at once
artist.set_facecolor(facecolors)
fig.canvas.draw()
elif isinstance(artist, Rectangle):
artist.set_facecolor("red")
artist.set_edgecolor("green")
fig.canvas.draw()
fig.canvas.mpl_connect("pick_event", on_pick)
plt.show()