首页 > 解决方案 > 如何将事件连接到 matplotlib.collections.PatchCollection

问题描述

使用matplotlib.collections.PatchCollection,我创建了一个显示六边形网格的 pyplot 图: 六边形

现在,我想让情节具有交互性,即添加某种形式的事件处理。特别是,我希望能够将光标悬停在任何六边形上,并且当我这样做时,我想用某种颜色填充所有相邻的六边形。

但是,让我们从简单的开始:如何将补丁(即六边形)连接到事件?

我已将每个六边形的中心点的坐标存储在一个 numpy 数组中。所以,我需要一种方法来告诉我点击的六边形的索引,或者我的光标当前已经结束。总共有 100 个六边形。当我点击 43 号六边形时,我只需要得到这个索引,然后,我想我知道如何获得与所有邻居的距离。但是我如何获得这个索引呢?

有人知道吗?

标签: pythonmatplotlibevent-handling

解决方案


PatchCollection与所有集合一样,有一个属性contains()可以告诉您触发事件的是集合的哪个成员(如果有)。

唯一的“技巧”是你必须确保你最初有一个与你的集合中成员数量相同大小的 facecolors 数组,否则事情会变得一团糟。在这里,我PathCollection.set_facecolors()在创建后使用以确保这一点。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection


def hover(event):
    if event.inaxes == ax:
        cont, ind = p.contains(event)
        if cont:
            idx = ind['ind'][0]
            colors = p.get_facecolors()
            colors[idx] = highlight_color
            p.set_facecolors(colors)
        else:
            p.set_facecolors([default_color] * N)
    fig.canvas.draw()


default_color = (0, 0, 1, 1)
highlight_color = (1, 0, 0, 1)

N = 10
r = 1
x, y = np.random.randint(10, 50, size=(2, N))
patches = [Circle((xi, yi), r) for xi, yi in zip(x, y)]
p = PatchCollection(patches)
p.set_facecolors([default_color] * N)

fig, ax = plt.subplots()
ax.add_collection(p)
ax.set_xlim(0, 50)
ax.set_ylim(0, 50)

fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()

推荐阅读