Skip to content

Commit d61ebe9

Browse files
authored
Merge pull request #23140 from Mr-Milk/legend-title-alignment
ENH: add alignment for labels in legend
2 parents 54bbf20 + b9cdf3e commit d61ebe9

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Legend can control alignment of title and handles
2+
-------------------------------------------------
3+
4+
`.Legend` now supports control the alignment of title and handles via the
5+
keyword argument ``alignment``. You can also use `.Legend.set_alignment`
6+
to control the alignment on existing Legends.

lib/matplotlib/legend.py

+42-3
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ def _update_bbox_to_anchor(self, loc_in_canvas):
257257
to set the fontsize alongside other font properties, use the *size*
258258
parameter in *title_fontproperties*.
259259
260+
alignment : {'center', 'left', 'right'}, default: 'center'
261+
The alignment of the legend title and the box of entries. The entries
262+
are aligned as a single block, so that markers always lined up.
263+
260264
borderpad : float, default: :rc:`legend.borderpad`
261265
The fractional whitespace inside the legend border, in font-size units.
262266
@@ -336,6 +340,7 @@ def __init__(
336340
frameon=None, # draw frame
337341
handler_map=None,
338342
title_fontproperties=None, # properties for the legend title
343+
alignment="center", # control the alignment within the legend box
339344
*,
340345
ncol=1 # synonym for ncols (backward compatibility)
341346
):
@@ -505,6 +510,9 @@ def val_or_rc(val, rc_name):
505510
)
506511
self._set_artist_props(self.legendPatch)
507512

513+
_api.check_in_list(["center", "left", "right"], alignment=alignment)
514+
self._alignment = alignment
515+
508516
# init with null renderer
509517
self._init_legend_box(handles, labels, markerfirst)
510518

@@ -804,7 +812,7 @@ def _init_legend_box(self, handles, labels, markerfirst=True):
804812
self._legend_title_box = TextArea("")
805813
self._legend_box = VPacker(pad=self.borderpad * fontsize,
806814
sep=self.labelspacing * fontsize,
807-
align="center",
815+
align=self._alignment,
808816
children=[self._legend_title_box,
809817
self._legend_handle_box])
810818
self._legend_box.set_figure(self.figure)
@@ -867,10 +875,41 @@ def get_texts(self):
867875
r"""Return the list of `~.text.Text`\s in the legend."""
868876
return silent_list('Text', self.texts)
869877

878+
def set_alignment(self, alignment):
879+
"""
880+
Set the alignment of the legend title and the box of entries.
881+
882+
The entries are aligned as a single block, so that markers always
883+
lined up.
884+
885+
Parameters
886+
----------
887+
alignment : {'center', 'left', 'right'}.
888+
889+
"""
890+
_api.check_in_list(["center", "left", "right"], alignment=alignment)
891+
self._alignment = alignment
892+
self._legend_box.align = alignment
893+
894+
def get_alignment(self):
895+
"""Get the alignment value of the legend box"""
896+
return self._legend_box.align
897+
870898
def set_title(self, title, prop=None):
871899
"""
872-
Set the legend title. Fontproperties can be optionally set
873-
with *prop* parameter.
900+
Set legend title and title style.
901+
902+
Parameters
903+
----------
904+
title : str
905+
The legend title.
906+
907+
prop : `.font_manager.FontProperties` or `str` or `pathlib.Path`
908+
The font properties of the legend title.
909+
If a `str`, it is interpreted as a fontconfig pattern parsed by
910+
`.FontProperties`. If a `pathlib.Path`, it is interpreted as the
911+
absolute path to a font file.
912+
874913
"""
875914
self._legend_title_box._text.set_text(title)
876915
if title:

lib/matplotlib/tests/test_legend.py

+19
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,25 @@ def test_legend_title_fontprop_fontsize():
607607
assert leg5.get_title().get_fontsize() == 20
608608

609609

610+
@pytest.mark.parametrize('alignment', ('center', 'left', 'right'))
611+
def test_legend_alignment(alignment):
612+
fig, ax = plt.subplots()
613+
ax.plot(range(10), label='test')
614+
leg = ax.legend(title="Aardvark", alignment=alignment)
615+
assert leg.get_children()[0].align == alignment
616+
assert leg.get_alignment() == alignment
617+
618+
619+
@pytest.mark.parametrize('alignment', ('center', 'left', 'right'))
620+
def test_legend_set_alignment(alignment):
621+
fig, ax = plt.subplots()
622+
ax.plot(range(10), label='test')
623+
leg = ax.legend()
624+
leg.set_alignment(alignment)
625+
assert leg.get_children()[0].align == alignment
626+
assert leg.get_alignment() == alignment
627+
628+
610629
@pytest.mark.parametrize('color', ('red', 'none', (.5, .5, .5)))
611630
def test_legend_labelcolor_single(color):
612631
# test labelcolor for a single color

0 commit comments

Comments
 (0)