0

I have a suptitle object that will sometimes be wrapped, using the built in wrapping functionality of Matplotlib. However, when trying to get the height of the suptitle, I seem to always get the height corresponding to one line. Where am I going wrong? This is what I'm trying with:

from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

fig = Figure((4, 4))
FigureCanvas(fig)

text_1 = "I'm a short text"
text_2 = "I'm a longer text that will be wrapped autoamtically by Matplotlib, using wrap=True"

title = fig.suptitle(text_1, wrap=True)
fig.canvas.draw()  # Draw text to find out how big it is
bbox = title.get_window_extent()
print(bbox.width)  # 105
print(bbox.height)  # 14

title = fig.suptitle(text_2, wrap=True)
fig.canvas.draw()  # Draw text to find out how big it is
bbox = title.get_window_extent()
print(bbox.width)  # 585 <-- This looks about right
print(bbox.height)  # Still 14 even though this time the text is wrapped!

The same thing happens with Text objects (using something like fig.text(0.5, 0.5, text_1, wrap=True).

leo
  • 8,106
  • 7
  • 48
  • 80
  • It may sound supprising, but the text is never actually wrapped inside the figure. It is only drawn in a wrapped fashion, such that appears wrapped in the final output. [This is the original post](https://stackoverflow.com/questions/4018860/text-box-with-line-wrapping-in-matplotlib) where wrapping was introduced. You may read through the code to understand it. – ImportanceOfBeingErnest Jun 07 '18 at 14:24
  • @ImportanceOfBeingErnest Oh, I wouldn't have guessed. Thanks. Any idea how to find out the final size of the text? Or at least the number of lines it was broken up into? – leo Jun 07 '18 at 14:32
  • No sorry, I don't have any idea as of now. – ImportanceOfBeingErnest Jun 07 '18 at 14:56

1 Answers1

0

Thank you @ImportanceOfBeingErnest for pointing out that this is not really possible. Here is one workaround, that kind of works, by checking the number of lines the text is broken up into, and multiplying by the approximate line-height. This works when automatically inserted breaks are mixed with manually (i.e. there is an "\n" in the text), but will be off by a number of pixels. Any more precise suggestions welcome.

def get_text_height(fig, obj):
    """ Get the approximate height of a text object.
    """
    fig.canvas.draw()  # Draw text to find out how big it is
    t = obj.get_text()
    r = fig.canvas.renderer
    w, h, d = r.get_text_width_height_descent(t, obj._fontproperties,
                                              ismath=obj.is_math_text(t))
    num_lines = len(obj._get_wrapped_text().split("\n"))
    return (h * num_lines)

text = "I'm a long text that will be wrapped automatically by Matplotlib, using wrap=True"
obj = fig.suptitle(text, wrap=True)
height = get_text_height(fig, obj)
print(height)  # 28 <-- Close enough! (In reality 30)
leo
  • 8,106
  • 7
  • 48
  • 80