Хорошо, я знаю, что это не ответ, но комментарии не позволяют мне проводить такого рода мозговой штурм. Я попробовал пару вещей и заметил следующее. Когда вы печатаете axes
из legendHandles
художников в вашем for l oop, он возвращает None
для обеих легенд в случае диаграммы разброса / PathCollection
художников. Однако в случае «нормальных» художников plot / Line2D
он возвращает объекты осей! И даже более того; хотя в терминале их представления кажутся одинаковыми (AxesSubplot(0.125,0.11;0.775x0.77)
), если вы проверите, являются ли они == ax2
, для legendHandles
исполнителя из legend1
он возвращает False
, а для одного из legend2
, возвращается True
. Что здесь происходит?
Итак, я попытался не только удалить legend1
из ax1
и снова добавить его в ax2
, но также сделать то же самое с объектом legendHandles
. Но это не позволяет мне сделать это:
NotImplementedError: cannot remove artist
Мне кажется, что вы обнаружили ошибку или, по крайней мере, непоследовательное поведение. Вот код того, что я пробовал до сих пор, на случай, если кто-то еще захочет поиграть с ним дальше.
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Qt5Agg')
import numpy as np
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
X = np.linspace(0, 2*np.pi, 100)
Y1 = X**0.5 * np.sin(X)
Y2 = -np.cos(X)
USE_LINES = True # <--- set this to True or False to test both cases.
if USE_LINES:
ax1.plot(X, Y1, color="green", label="$Y_1$")
ax2.plot(X, Y2, color="red", label="$Y_2$")
else:
ax1.scatter(X, Y1, color="green", label="$Y_1$")
ax2.scatter(X, Y2, color="red", label="$Y_2$")
# Put both legends on ax2 so that pick events also work for ax1's legend.
legend1 = ax1.legend(loc="upper left")
legend2 = ax2.legend(loc="upper right")
legend1.remove()
ax2.add_artist(legend1)
# legend1.legendHandles[0].remove()
# ax2.add_artist(legend1.legendHandles[0])
for n, legend in enumerate((legend1, legend2)):
legend_item = legend.legendHandles[0]
legend_item.set_gid(n+1)
legend_item.set_picker(10)
print(
f'USE_LINES = {USE_LINES}', f'legend{n+1}',
legend_item.axes.__repr__() == legend.axes.__repr__(),
legend_item.axes == legend.axes,
legend_item.axes.__repr__() == ax2.__repr__(),
legend_item.axes == ax2, type(legend_item),
)
# When a legend element is picked, hide/show the associated curve.
def on_graph_pick_event(event):
gid = event.artist.get_gid()
print(f"Picked Y{gid}'s legend.")
ax = {1: ax1, 2: ax2}[gid]
artist = ax.lines[0] if USE_LINES else ax.collections[0]
artist.set_visible(not artist.get_visible())
plt.draw()
fig.canvas.mpl_connect("pick_event", on_graph_pick_event)
plt.show()