Код для этого примера в основном взят из Маркер разделения и строки в легенде - Matplotlib - за исключением того, что я добавил взаимодействие для переключения легенды из https://matplotlib.org/3.1.1/gallery/event_handling/legend_picking.html
Этокак выглядит поведение:
![Figure_1](https://i.stack.imgur.com/ZEeoZ.gif)
Давайте на время пока проигнорируем логику переключения реальных линий графика.
Моя проблема здесь в том, что когда я нажимаю на записи в легенде, которые являются только маркерами - они НЕ меняют ни альфа, ни цвет - даже если я использовал set_markerfacecolor()
специально, чтобы заставить их цвет.
С другой стороны, когда я нажимаю на записи в легенде, которые являются только строками, они без проблем меняют альфу.
Итак, как я могу получить маркеры на легенде, чтобытакже изменить альфа (или цвет) при нажатии / выборе / переключении?
Распечатки, которые я получаю в терминале за первые несколько нажатий на анимированном GIF:
$ python3 /tmp/test3.py
(0.0, 0.0, 0.0, 1)
(0.2, 0.2, 0.2, 0.2)
(1.0, 1.0, 1.0, 1.0)
(0.2, 0.2, 0.2, 0.2)
(0.0, 0.0, 0.0, 1)
(0.2, 0.2, 0.2, 0.2)
(1.0, 1.0, 1.0, 1.0)
(0.2, 0.2, 0.2, 0.2)
(0.0, 0.0, 0.0, 1)
(0.2, 0.2, 0.2, 0.2)
(1.0, 1.0, 1.0, 1.0)
(0.2, 0.2, 0.2, 0.2)
(0.0, 0.0, 1.0, 1)
(0.2, 0.2, 0.2, 0.2)
...
Код:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import colors
def function_to_split(hand,labl,dividor):
Hand_L=[]
Hand_M=[]
Labl_L=[]
Labl_M=[]
for h,l in zip(hand,labl):
co=h.get_color()
ls=h.get_linestyle()
lw=h.get_linewidth()
mk=h.get_marker()
mew=h.get_markeredgewidth()
ms=h.get_markersize()
LABS=l.split(dividor)
if len(LABS) != 2:
print('Split Legends Error: Only exactly 1 Dividor is accepted.')
print(' Currently ' + str(len(LABS)-1) + ' dividors were given')
return hand,labl
#Line and Color
LICO = plt.Line2D((0,1),(0,0), color=co, marker='', linestyle=ls,linewidth=lw)
#Marker
MARK = plt.Line2D((0,1),(0,0), color='k', marker=mk, markeredgewidth=mew, markersize=ms, linestyle='')
if LABS[0] not in Labl_L:
Hand_L.append(LICO)
Labl_L.append(LABS[0])
if LABS[1] not in Labl_M:
Hand_M.append(MARK)
Labl_M.append(LABS[1])
return Hand_L+Hand_M,Labl_L+Labl_M
pi=3.14
xx=np.linspace(0,2*pi,100)
fig = plt.figure()
ax = fig.add_subplot(111)
phases=[0,pi/4,pi/2]
markers=['s','o','^']
lines = []
for phase,mk in zip(phases,markers):
labeltext='Sine' + '*' + str(phase)
F=[np.sin(x+phase) for x in xx]
line, = ax.plot(xx,F,color='b',marker=mk,label=labeltext)
lines.append(line)
labeltext='Cosine' + '*' + str(phase)
F=[np.cos(x+phase) for x in xx]
line, = ax.plot(xx,F,color='g',marker=mk,label=labeltext)
lines.append(line)
hand, labl = ax.get_legend_handles_labels()
hand, labl = function_to_split(hand,labl,'*')
leg = ax.legend(hand,labl)
#plt.savefig('Figure.png')
# https://matplotlib.org/3.1.1/gallery/event_handling/legend_picking.html
lined = dict()
for legline, origline in zip(leg.get_lines(), lines):
legline.set_picker(5) # 5 pts tolerance
lined[legline] = origline
# NOTE: in the legend, can just click on line to trigger onpick()
# however, clicking on standalone marker in legend won't trigger,
# so you have to click in the whitespace around the legend marker to trigger onpick()!
def onpick(event):
# on the pick event, find the orig line corresponding to the
# legend proxy line, and toggle the visibility
legline = event.artist
origline = lined[legline]
vis = not origline.get_visible()
origline.set_visible(vis)
# Change the alpha on the line in the legend so we can see what lines
# have been toggled
# NB: .set_alpha() works only on lines, not on markers!
mfcol = colors.to_rgba(legline.get_markerfacecolor())
print(mfcol)
if vis:
legline.set_markerfacecolor( (1.0, 1.0, 1.0, 1.0) )
legline.set_alpha(1.0)
else:
legline.set_markerfacecolor( (0.2, 0.2, 0.2, 0.2) )
legline.set_alpha(0.2)
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()