检索在单击处理程序中接收到鼠标单击事件的 matplotlib Artist

问题描述 投票:0回答:1

我有一个 python 程序,它创建一个 matplotlib 图形和添加到其中的许多矩形艺术家。每个艺术家都会安装一个通用的单击处理程序,当鼠标在矩形内单击时会调用该处理程序。问题是我不知道如何确定单击了哪个矩形。传递给处理程序的单击事件确实包括单击时鼠标的位置,但我必须测试每个矩形以查看哪个矩形包含该点。

必须有一种更简单的方法来做到这一点。

python matplotlib click
1个回答
0
投票

矩形可能已以各种方式添加到斧头:

  • 如果来自
    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()

© www.soinside.com 2019 - 2024. All rights reserved.