You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pick events on legends work perfectly unless the legend is moved out of the axes using bbox_to_anchor. After that, the pick event gets called twice for a single mouse click.
The following code demonstrates the error. The bug appears when the legend line is clicked: the line toggles twice on a mouse click instead of once.
'''
Toggle plot line-styles between ':' and '-' when line is clicked or
when the corresponding legend line is clicked.
'''
import pylab
import numpy
# Create data for plotting
t = numpy.linspace(0, 1.0, 100)
a = numpy.sin(2*numpy.pi*t)
# Set up figure
fig = pylab.figure()
ax = pylab.subplot(111)
# Plot figures
lines = []
for i in range(5):
line = ax.plot(t, (i+1)*a, linestyle=':', picker=5, label='line%d'%(i+1))
lines.append(line[0]) # Save plot lines
# Create legend
leg = ax.legend(bbox_to_anchor=(1.01, 1), loc=2) # Does not work as expected
# leg = ax.legend() # Works!!
# Get legend lines
leglines = leg.get_lines()
# Set event for legend lines
for line in leglines:
line.set_picker(5)
# Create a 2 way mapping between legend lines <-> plot lines
line2leg = dict(zip(lines+leglines, leglines+lines))
# Define event function
def onpick(event):
thisline = event.artist
if thisline.get_linestyle()==':':
print ": -> -" # For debugging
thisline.set_linestyle('-')
line2leg[thisline].set_linestyle('-')
else:
print "- -> :" # For debugging
thisline.set_linestyle(':')
line2leg[thisline].set_linestyle(':')
fig.canvas.draw()
# connect event function
fig.canvas.mpl_connect('pick_event', onpick)
pylab.show()
The main issue is that the picker gets called twice as the legend.get_children() method returns more than just children. Note that this happens regardless of whether the legend is placed in the axes or outside with the bbox_to_anchor. Why doesn't the picker get called twice when inside the axis? Due to the following code
# Pick children
for a in self.get_children():
# make sure the event happened in the same axes
ax = getattr(a, 'axes', None)
if mouseevent.inaxes is None or mouseevent.inaxes == ax:
# we need to check if mouseevent.inaxes is None
# because some objects associated with an axes (e.g., a
# tick label) can be outside the bounding box of the
# axes and inaxes will be None
a.pick(mouseevent)
The offsetbox that legend use as a child does not contain an axes property (perhaps incorrectly so) which means mouseevent.inaxes == ax is not satisfied on the actual legend offsetbox itself resulting in only one call. When a user clicks outside of the axes when the legend is bound outside, mouseevent.inaxes is None holds true so mouseevent.inaxes does not even get evaluated and both get called.
Bottom line, PR #2755 fixes the issue with incorrect children traversal tree and fixes the problem you see here while clicking on the legend outside of the axes but exposes an issue or bug with the picking logic while within the axes.
Pick events on legends work perfectly unless the legend is moved out of the axes using bbox_to_anchor. After that, the pick event gets called twice for a single mouse click.
The following code demonstrates the error. The bug appears when the legend line is clicked: the line toggles twice on a mouse click instead of once.
(See also: http://stackoverflow.com/questions/16278358/double-event-registered-on-mouse-click-if-legend-is-outside-axes)
The text was updated successfully, but these errors were encountered: