Double event registered on mouse-click if legend is outside axes

后端 未结 3 1528
暗喜
暗喜 2021-01-20 03:21

I have to plot several data sets in one plot. It is useful to be able to highlight one or more of the plots in order to compare them. For this, I toggle the line style of th

3条回答
  •  春和景丽
    2021-01-20 04:09

    If you monkey patch Artist.pick with the following:

    matplotlib.artist.Artist.orig_pick = matplotlib.artist.Artist.pick
    def nu_pick(self, me):
        print self
        matplotlib.artist.Artist.orig_pick(self, me)
    
    matplotlib.artist.Artist.pick = nu_pick
    

    You can look at how the artists recurse on a pick event. (Each Artist object calls pick on it's self and then on all of it's children). For reasons I don't understand, there are two copies of each line in the drawing area of the legend (and it behaves differently when it is inside and outside).

    A way-hacky solution is to just count how many times the leglines have been hit, and only toggle on the odd ones:

    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))
    count_dict = dict((l, 0) for l in lines )
    # Define event function
    def onpick(event):
        thisline = event.artist
        print event
        print thisline
        if thisline in lines:
            print 'lines'
            count_dict[thisline] = 0
        elif thisline in leglines:
            print 'leglines'
            thisline = line2leg[thisline]
            count_dict[thisline] += 1
        print 'added'
        if (count_dict[thisline] % 2) == 1:
            print count_dict[thisline]
            return
        print 'tested'
        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()
    

    (I left all my de-bugging statements in).

    Pretty sure this is a bug, if you don't want to create an issue on github I will.

提交回复
热议问题