【发布时间】:2019-05-07 04:53:12
【问题描述】:
这个问题和下面两个关系密切,但是这个问题比较笼统。
Matplotlib pick event order for overlapping artists
Multiple pick events interfering
问题:
在单个画布上选择重叠的艺术家时,会为每个艺术家创建单独的选择事件。在下面的示例中,单击红点会调用两次on_pick,一次调用lines,一次调用points。由于points 位于该线之上(考虑到它们各自的zorder 值),我宁愿只为最高艺术家生成一个选择事件(在本例中:points)。
示例:
import numpy as np
from matplotlib import pyplot
def on_pick(event):
if event.artist == line:
print('Line picked')
elif event.artist == points:
print('Point picked')
# create axes:
pyplot.close('all')
ax = pyplot.axes()
# add line:
x = np.arange(10)
y = np.random.randn(10)
line = ax.plot(x, y, 'b-', zorder=0)[0]
# add points overlapping the line:
xpoints = [2, 4, 7]
points = ax.plot(x[xpoints], y[xpoints], 'ro', zorder=1)[0]
# set pickers:
line.set_picker(5)
points.set_picker(5)
ax.figure.canvas.mpl_connect('pick_event', on_pick)
pyplot.show()
凌乱的解决方案:
一种解决方案是使用 Matplotlib 的 button_press_event,然后计算鼠标和所有艺术家之间的距离,如下所示。然而,这个解决方案相当混乱,因为添加额外的重叠艺术家会使这段代码变得相当复杂,增加要检查的案例和条件的数量。
def on_press(event):
if event.xdata is not None:
x,y = event.xdata, event.ydata #mouse click coordinates
lx,ly = line.get_xdata(), line.get_ydata() #line point coordinates
px,py = points.get_xdata(), points.get_ydata() #points
dl = np.sqrt((x - lx)**2 + (y - ly)**2) #distances to line points
dp = np.sqrt((x - px)**2 + (y - py)**2) #distances to points
if dp.min() < 0.05:
print('Point selected')
elif dl.min() < 0.05:
print('Line selected')
pyplot.close('all')
ax = pyplot.axes()
# add line:
x = np.arange(10)
y = np.random.randn(10)
line = ax.plot(x, y, 'b-', zorder=0)[0]
# add points overlapping the line:
xpoints = [2, 4, 7]
points = ax.plot(x[xpoints], y[xpoints], 'ro', zorder=1)[0]
# set picker:
ax.figure.canvas.mpl_connect('button_press_event', on_press)
pyplot.show()
问题摘要: 有没有更好的方法可以从一组重叠的艺术家中选择最高的艺术家?
理想情况下,我希望能够做这样的事情:
pyplot.set_pick_stack( [points, line] )
暗示points 将被选中而不是line 以进行重叠选择。
【问题讨论】:
-
用
event.artist.get_zorder()怎么样? -
因为我想要一个单一的选择事件,其艺术家在指定鼠标点的所有艺术家中具有最大的 zorder 值。 zorder 确实可以在上面的 'button_press_event' 解决方案中使用,但是这个 'button_press_event' 只是一个 hack,而不是一个选择事件。
-
我已经重写了我的答案,包括一个使用提示进行选择事件的示例。
标签: python matplotlib event-handling