Skip to content

Commit 922c950

Browse files
authored
Merge pull request #11035 from jklymak/fix-suptitle-CL
FIX: constrained_layout and repeated calls to suptitle
2 parents fb98a9a + 3ef6944 commit 922c950

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

lib/matplotlib/_constrained_layout.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
235235
ax._poslayoutbox.constrain_left_margin(0, strength='weak')
236236

237237
# do layout for suptitle.
238-
if fig._suptitle is not None:
238+
if fig._suptitle is not None and fig._suptitle._layoutbox is not None:
239239
sup = fig._suptitle
240240
bbox = invTransFig(sup.get_window_extent(renderer=renderer))
241241
height = bbox.y1 - bbox.y0

lib/matplotlib/figure.py

+22-14
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ def get_window_extent(self, *args, **kwargs):
678678
"""
679679
return self.bbox
680680

681-
def suptitle(self, t, *, x=.5, y=.98, **kwargs):
681+
def suptitle(self, t, **kwargs):
682682
"""
683683
Add a centered title to the figure.
684684
@@ -732,6 +732,11 @@ def suptitle(self, t, *, x=.5, y=.98, **kwargs):
732732
733733
>>> fig.suptitle('This is the figure title', fontsize=12)
734734
"""
735+
manual_position = ('x' in kwargs or 'y' in kwargs)
736+
737+
x = kwargs.pop('x', 0.5)
738+
y = kwargs.pop('y', 0.98)
739+
735740
if ('horizontalalignment' not in kwargs) and ('ha' not in kwargs):
736741
kwargs['horizontalalignment'] = 'center'
737742
if ('verticalalignment' not in kwargs) and ('va' not in kwargs):
@@ -751,19 +756,22 @@ def suptitle(self, t, *, x=.5, y=.98, **kwargs):
751756
sup.remove()
752757
else:
753758
self._suptitle = sup
754-
if self._layoutbox is not None:
755-
# assign a layout box to the suptitle...
756-
figlb = self._layoutbox
757-
self._suptitle._layoutbox = layoutbox.LayoutBox(
758-
parent=figlb,
759-
name=figlb.name+'.suptitle')
760-
for child in figlb.children:
761-
if not (child == self._suptitle._layoutbox):
762-
w_pad, h_pad, wspace, hspace = \
763-
self.get_constrained_layout_pads(
764-
relative=True)
765-
layoutbox.vstack([self._suptitle._layoutbox, child],
766-
padding=h_pad*2., strength='required')
759+
self._suptitle._layoutbox = None
760+
if self._layoutbox is not None and not manual_position:
761+
w_pad, h_pad, wspace, hspace = \
762+
self.get_constrained_layout_pads(relative=True)
763+
figlb = self._layoutbox
764+
self._suptitle._layoutbox = layoutbox.LayoutBox(
765+
parent=figlb, artist=self._suptitle,
766+
name=figlb.name+'.suptitle')
767+
# stack the suptitle on top of all the children.
768+
# Some day this should be on top of all the children in the
769+
# gridspec only.
770+
for child in figlb.children:
771+
if child is not self._suptitle._layoutbox:
772+
layoutbox.vstack([self._suptitle._layoutbox,
773+
child],
774+
padding=h_pad*2., strength='required')
767775
self.stale = True
768776
return self._suptitle
769777

lib/matplotlib/tests/test_constrainedlayout.py

+40
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,43 @@ def test_constrained_layout20():
344344
ax = fig.add_axes([0, 0, 1, 1])
345345
mesh = ax.pcolormesh(gx, gx, img)
346346
fig.colorbar(mesh)
347+
348+
349+
def test_constrained_layout21():
350+
'#11035: repeated calls to suptitle should not alter the layout'
351+
fig, ax = plt.subplots(constrained_layout=True)
352+
353+
fig.suptitle("Suptitle0")
354+
fig.canvas.draw()
355+
extents0 = np.copy(ax.get_position().extents)
356+
357+
fig.suptitle("Suptitle1")
358+
fig.canvas.draw()
359+
extents1 = np.copy(ax.get_position().extents)
360+
361+
np.testing.assert_allclose(extents0, extents1)
362+
363+
364+
def test_constrained_layout22():
365+
'#11035: suptitle should not be include in CL if manually positioned'
366+
fig, ax = plt.subplots(constrained_layout=True)
367+
368+
fig.canvas.draw()
369+
extents0 = np.copy(ax.get_position().extents)
370+
371+
fig.suptitle("Suptitle", y=0.5)
372+
fig.canvas.draw()
373+
extents1 = np.copy(ax.get_position().extents)
374+
375+
np.testing.assert_allclose(extents0, extents1)
376+
377+
378+
def test_constrained_layout23():
379+
'''
380+
Comment in #11035: suptitle used to cause an exception when
381+
reusing a figure w/ CL with ``clear=True``.
382+
'''
383+
384+
for i in range(2):
385+
fig, ax = plt.subplots(num="123", constrained_layout=True, clear=True)
386+
fig.suptitle("Suptitle{}".format(i))

0 commit comments

Comments
 (0)