Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add legend.linewidth parameter to control legend box edge linewidth#30780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
timhoffm merged 8 commits intomatplotlib:mainfrommanit2004:main
Nov 29, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletionsdoc/release/next_whats_new/legend_line_width.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
``legend.linewidth`` rcParam and parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A new rcParam ``legend.linewidth`` has been added to control the line width of
the legend's box edges. When set to ``None`` (the default), it inherits the
value from ``patch.linewidth``. This allows for independent control of the
legend frame line width without affecting other elements.

The `.Legend` constructor also accepts a new *linewidth* parameter to set the
legend frame line width directly, overriding the rcParam value.

.. plot::
:include-source: true
:alt: A line plot with a legend showing a thick border around the legend box.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Using theplot directive here will mean we get an output image with the example. Seehere for an example of how that’s done.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='data')
ax.legend(linewidth=2.0) # Thick legend box edge
plt.show()
10 changes: 10 additions & 0 deletionslib/matplotlib/legend.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -196,6 +196,12 @@ def _update_bbox_to_anchor(self, loc_in_canvas):
The legend's background patch edge color.
If ``"inherit"``, use :rc:`axes.edgecolor`.

linewidth : float or None, default: :rc:`legend.linewidth`
The legend's background patch edge linewidth.
If ``None``, use :rc:`patch.linewidth`.

.. versionadded:: 3.11

mode : {"expand", None}
If *mode* is set to ``"expand"`` the legend will be horizontally
expanded to fill the Axes area (or *bbox_to_anchor* if defines
Expand DownExpand Up@@ -385,6 +391,7 @@ def __init__(
framealpha=None, # set frame alpha
edgecolor=None, # frame patch edgecolor
facecolor=None, # frame patch facecolor
linewidth=None, # frame patch linewidth

bbox_to_anchor=None, # bbox to which the legend will be anchored
bbox_transform=None, # transform for the bbox
Expand DownExpand Up@@ -526,9 +533,12 @@ def __init__(

fancybox = mpl._val_or_rc(fancybox, "legend.fancybox")

linewidth = mpl._val_or_rc(linewidth, "legend.linewidth")

self.legendPatch = FancyBboxPatch(
xy=(0, 0), width=1, height=1,
facecolor=facecolor, edgecolor=edgecolor,
linewidth=linewidth,
# If shadow is used, default to alpha=1 (#8943).
alpha=(framealpha if framealpha is not None
else 1 if shadow
Expand Down
1 change: 1 addition & 0 deletionslib/matplotlib/legend.pyi
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,6 +85,7 @@ class Legend(Artist):
framealpha:float|None= ...,
edgecolor:Literal["inherit"]|ColorType|None= ...,
facecolor:Literal["inherit"]|ColorType|None= ...,
linewidth:float|None= ...,
bbox_to_anchor:BboxBase
|tuple[float,float]
|tuple[float,float,float,float]
Expand Down
1 change: 1 addition & 0 deletionslib/matplotlib/mpl-data/matplotlibrc
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -562,6 +562,7 @@
#legend.framealpha: 0.8 # legend patch transparency
#legend.facecolor: inherit # inherit from axes.facecolor; or color spec
#legend.edgecolor: 0.8 # background patch boundary color
#legend.linewidth: None # line width of the legend frame, None means inherit from patch.linewidth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It seems we have a mixture already in that we sometimes use "inherit" and sometimes None. We should do an analysis of the cases and decide which one to use in the future.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I see the point about consistency. I followed the edgecolor pattern which uses "inherit". Happy to adjust based on the team's preferred convention.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Unfortunately, we are inconsistent already.

rcParams using inherit:

  • legend.facecolor: inherit # inherit from axes.facecolor; or color spec
  • legend.edgecolor
  • xtick.labelcolor
  • ytick.labelcolor

rcParams using None:

  • grid.major.color: None # If None defaults to grid.color
  • grid.major.linestyle: None # If None defaults to grid.linestyle
  • grid.major.linewidth: None # If None defaults to grid.linewidth
  • grid.major.alpha: None # If None defaults to grid.alpha
  • grid.minor.color: None # If None defaults to grid.color
  • grid.minor.linestyle: None # If None defaults to grid.linestyle
  • grid.minor.linewidth: None # If None defaults to grid.linewidth
  • grid.minor.alpha: None # If None defaults to grid.alpha
  • legend.labelcolor: None # None: use text.color
  • contour.linewidth: None # {float, None} Size of the contour line widths. If set to None, it falls back toline.linewidth.

rcParams using auto

  • axes.titlecolor: auto # color of the axes title, auto falls back to text.color as default value
  • savefig.facecolor: auto # figure face color when saving

Summary
"auto" is out. The decision is between None and inherit. There are arguments for both.
I'm ok with sticking withNone for now.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks for clarifying. Is there anything needed from my side to move this PR forward being merged?

#legend.fancybox: True # if True, use a rounded box for the
# legend background, else a rectangle
#legend.shadow: False # if True, give background a shadow effect
Expand Down
2 changes: 2 additions & 0 deletionslib/matplotlib/rcsetup.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1184,6 +1184,8 @@ def _convert_validator_spec(key, conv):
"legend.frameon": validate_bool,
# alpha value of the legend frame
"legend.framealpha": validate_float_or_None,
# linewidth of legend frame
"legend.linewidth": validate_float_or_None,

## the following dimensions are in fraction of the font size
"legend.borderpad": validate_float, # units are fontsize
Expand Down
31 changes: 31 additions & 0 deletionslib/matplotlib/tests/test_legend.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1669,6 +1669,37 @@ def test_boxplot_legend_labels():
assert all(x.get_label().startswith("_") for x in bp4['medians'][1:])


def test_legend_linewidth():
"""Test legend.linewidth parameter and rcParam."""
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='data')

# Test direct parameter
leg = ax.legend(linewidth=2.5)
assert leg.legendPatch.get_linewidth() == 2.5

# Test rcParam
with mpl.rc_context({'legend.linewidth': 3.0}):
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='data')
leg = ax.legend()
assert leg.legendPatch.get_linewidth() == 3.0

# Test None default (should inherit from patch.linewidth)
with mpl.rc_context({'legend.linewidth': None, 'patch.linewidth': 1.5}):
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='data')
leg = ax.legend()
assert leg.legendPatch.get_linewidth() == 1.5

# Test that direct parameter overrides rcParam
with mpl.rc_context({'legend.linewidth': 1.0}):
fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='data')
leg = ax.legend(linewidth=4.0)
assert leg.legendPatch.get_linewidth() == 4.0


def test_patchcollection_legend():
# Test that PatchCollection labels show up in legend and preserve visual
# properties (issue #23998)
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp