matplotlib + wxpython not sizing correctly with legend

前端 未结 1 584
忘了有多久
忘了有多久 2021-01-13 19:45

I have a matplotlib figure embedded in a wxpython frame with a few sizers. Everything works fine until I include a legend but then the sizers don\'t seem to be working with

相关标签:
1条回答
  • 2021-01-13 20:39

    It is re-sizing correctly, you just didn't tell it to do what you want it to do.

    The problem is this line:

    axes.legend(loc='center left', bbox_to_anchor=(1.05, 0.5))
    

    Pretty sure the bbox_to_anchor kwarg is over-ridding the loc kwarg and you are pegging the bottom left of the legend to (1.05, 0.5) in axes units. If the axes expands to fill your window, the left edge of the legend will always be 5% of the width axes to the right of the right edge of you axes, hence always out of view.

    You either need to put your legend someplace else or shrink your axes (in figure fraction).

    option 1 move the legend:

    axes.legend(bbox_to_anchor=(0.5, 0.5)) #find a better place this is in the center
    

    option 2 move the axes + resize the figure:

    axes.set_position([.1, .1, .5, .8]) # units are in figure fraction
    

    set_position

    fig = figure()
    axes = fig.add_subplot(111)
    
    for c in ['r', 'b', 'k']:
        vals = [20, 30, 40, 50, 80, 20, 50, 60, 70, 70, 80]
        shuffle(vals)
        axes.plot(range(len(vals)), vals, "-o", color=c, label=c*10)
    
    legend = axes.legend(loc='center left', bbox_to_anchor=(1.05, 0.5))
    

    enter image description here

    # adjust the figure size (in inches)
    fig.set_size_inches(fig.get_size_inches() * np.array([1.5, 1]), forward=True)
    
    # and the axes size (in figure fraction)
    # to (more-or-less) preserve the aspect ratio of the original axes
    # and show the legend
    pos = np.array(axes.get_position().bounds)
    pos[2] = .66
    axes.set_position(pos)
    

    enter image description here

    option 3: automate option 2

    fig = figure() # use plt to set this up for demo purposes
    axes = fig.add_subplot(111) # add a subplot
    
    # control paramters 
    left_pad = .05 
    right_pad = .05
    
    # plot data
    for c in ['r', 'b', 'k']:
        vals = [20, 30, 40, 50, 80, 20, 50, 60, 70, 70, 80]
        shuffle(vals)
        axes.plot(range(len(vals)), vals, "-o", color=c, label=c*10)
    # set axes labels
    axes.set_xlabel('test x')
    axes.set_ylabel('test y')
    
    # make the legend
    legend = axes.legend(loc='center left', bbox_to_anchor=(1 + left_pad, 0.5))
    
    # function to 'squeeze' the legend into place
    def squeeze_legend(event):
        fig.tight_layout()
        right_frac = 1 - legend.get_window_extent().width / fig.get_window_extent().width - left_pad - right_pad
        fig.subplots_adjust(right=right_frac)
        fig.canvas.draw()
    
    # call it so the first draw is right
    squeeze_legend()
    
    # use the resize event call-back to make sure it works even if the window is re-sized
    fig.canvas.mpl_connect('resize_event', squeeze_legend)
    
    0 讨论(0)
提交回复
热议问题