Python: position text box fixed in corner and correctly aligned

前端 未结 1 1600
情话喂你
情话喂你 2021-01-13 00:34

I\'m trying to mimic the legend method in matplotlib.pyplot where one can use loc=\'lower right\' to position the legend box fixed

相关标签:
1条回答
  • 2021-01-13 00:54

    The quick-and-dirty way is to use right and top aligned text and place it at a fixed offset in points from the axes corner:

    import matplotlib.pyplot as plt
    
    # Define some names and variables to go in the text box.
    xn, yn, cod = 'r', 'p', 'abc'
    prec = 2
    ccl = [546.35642, 6785.35416]
    ect = [12.5235, 13.643241]
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.axis([-1, 10, -1, 1])
    
    # Generate text to write.
    text1 = "${}_{{t}} = {:.{p}f} \pm {:.{p}f}\; {c}$".format(xn, ccl[0],
        ect[0], c=cod, p=prec)
    text2 = "${}_{{t}} = {:.{p}f} \pm {:.{p}f}\; {c}$".format(yn, ccl[1],
        ect[1], c=cod, p=prec)
    text = text1 + '\n' + text2
    
    ax.annotate(text, xy=(1, 1), xytext=(-15, -15), fontsize=10,
        xycoords='axes fraction', textcoords='offset points',
        bbox=dict(facecolor='white', alpha=0.8),
        horizontalalignment='right', verticalalignment='top')
    
    plt.show()
    

    enter image description here

    Because we've specified top and right alignment, it works with your two edge cases:

    enter image description here

    enter image description here


    The downside of this is that the text is right-aligned. Ideally, you'd want the text alignment to be separate from the box alignment. The matplotlib.offsetbox module has a number of methods to handle things like this.

    If you want to mimic a legend box (down to the location codes), have a look at matplotlib.offsetbox.AnchoredText. (Note that you can adjust the padding, etc though the pad and borderpad kwargs: http://matplotlib.org/api/offsetbox_api.html#matplotlib.offsetbox.AnchoredOffsetbox )

    import matplotlib.pyplot as plt
    import matplotlib.offsetbox as offsetbox
    
    # Define some names and variables to go in the text box.
    xn, yn, cod = 'r', 'p', 'abc'
    prec = 5
    ccl = [546.35642, 6785.35416]
    ect = [12.5235, 13.643241]
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.axis([-1, 10, -1, 1])
    
    # Generate text to write.
    text1 = "${}_{{t}} = {:.{p}f} \pm {:.{p}f}\; {c}$".format(xn, ccl[0],
        ect[0], c=cod, p=prec)
    text2 = "${}_{{t}} = {:.{p}f} \pm {:.{p}f}\; {c}$".format(yn, ccl[1],
        ect[1], c=cod, p=prec)
    text = text1 + '\n' + text2
    
    ob = offsetbox.AnchoredText(text, loc=1)
    ax.add_artist(ob)
    
    plt.show()
    

    enter image description here

    One downside to this is that adjusting the font and box parameters for the result is a bit counter-intuitive. AnchoredText accepts a dictionary of font parameters as the prop kwarg. The box can be adjusted after initialization through the patch attribute. As a quick example:

    ob = offsetbox.AnchoredText(text, loc=1,
                        prop=dict(color='white', size=20))
    ob.patch.set(boxstyle='round', color='blue', alpha=0.5)
    ax.add_artist(ob)
    

    enter image description here

    0 讨论(0)
提交回复
热议问题