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

Conversation

@manit2004
Copy link
Contributor

@manit2004manit2004 commentedNov 22, 2025
edited
Loading

PR summary

Why is this change necessary?

Users can customize many aspects of legend appearance through rcParams (facecolor, edgecolor, framealpha, shadow, etc.), but there was no way to control the linewidth of the legend's box edges. This created an inconsistency in the customization API and required workarounds when users wanted legends with thicker or thinner frame lines to match their plot aesthetics.

What problem does it solve?

This solves the problem of not being able to independently control legend frame linewidth. Previously, the legend frame linewidth was implicitly tied to the default patch linewidth, making it impossible to have, for example, thin axes borders but thick legend borders, or vice versa.

What is the reasoning for this implementation?

The implementation follows matplotlib's existing pattern for legend customization:

  • Added a newlegend.linewidth rcParam (default:None)
  • WhenNone, it inherits fromaxes.linewidth for backward compatibility
  • Added alinewidth parameter toLegend.__init__() for per-legend control
  • The parameter is passed directly to theFancyBboxPatch that draws the legend frame

This approach is consistent with how other legend properties likeedgecolor andfacecolor work, making it intuitive for users already familiar with matplotlib's legend customization.

Minimum self-contained example:

importmatplotlib.pyplotaspltimportmatplotlibasmplimportnumpyasnpx=np.linspace(0,2*np.pi,100)fig,axes=plt.subplots(1,3,figsize=(12,4))# Default behavior (inherits axes.linewidth)axes[0].plot(x,np.sin(x),label='sin(x)')axes[0].legend()axes[0].set_title('Default (axes.linewidth=0.8)')# Set via rcParamsmpl.rcParams['legend.linewidth']=3.0axes[1].plot(x,np.cos(x),label='cos(x)')axes[1].legend()axes[1].set_title('Via rcParams (linewidth=3.0)')mpl.rcParams['legend.linewidth']=None# Reset# Set via parameteraxes[2].plot(x,np.sin(2*x),label='sin(2x)')axes[2].legend(linewidth=5.0,edgecolor='red')axes[2].set_title('Via parameter (linewidth=5.0)')plt.tight_layout()plt.show()

PR checklist

Copy link
Member

@rcomerrcomer left a comment
edited
Loading

Choose a reason for hiding this comment

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

Thanks for your work on this@manit2004. As well as my specific comments below, I think this should default to the patch linewidth. As you noted in your summary, that is what is currently used so having it as the default will give us backwards compatibility. I think that will clear up the image test failures.

This should also get atest to verify the behaviour.

value from ``axes.linewidth``. This allows for independent control of the
legend frame line width without affecting other elements.

..versionadded::3.10
Copy link
Member

Choose a reason for hiding this comment

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

The versionadded directive is not needed in the release notes. All these files will later be combined to make a single page for the release.Like this


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

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.

The legend's background patch edge linewidth.
If ``None``, use :rc:`axes.linewidth`.
.. versionadded:: 3.10
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
..versionadded::3.10
..versionadded::3.11

v3.10 is already released.

#legend.handletextpad: 0.8 # the space between the legend line and legend text
#legend.borderaxespad: 0.5 # the border between the axes and legend edge
#legend.columnspacing: 2.0 # column separation
#legend.linewidth: None # line width of the legend frame, None means inherit from axes.linewidth
Copy link
Member

Choose a reason for hiding this comment

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

I would move this up with edgecolor, etc. Although it is technically a size, it comes under the same style consideration as color and alpha. Also it is measured in points, not fraction of font size.

# legend properties
"legend.fancybox":validate_bool,
"legend.loc":_validate_legend_loc,
"legend.linewidth":validate_float_or_None,# linewidth of legend frame
Copy link
Member

Choose a reason for hiding this comment

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

Move this down with framealpha.

@rcomerrcomer linked an issueNov 23, 2025 that may beclosed by this pull request
@rcomerrcomer moved this toWaiting for author inFirst Time ContributorsNov 23, 2025
Copy link
Member

@rcomerrcomer left a comment

Choose a reason for hiding this comment

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

Thanks for the quick update@manit2004. Just a couple more minor comments but otherwise this looks great!

Comment on lines 537 to 538
iflinewidthisNone:
linewidth=mpl.rcParams["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.

Suggested change
iflinewidthisNone:
linewidth=mpl.rcParams["patch.linewidth"]

I think we can leave this asNone, and theFancyBboxPatch will take care of swapping it for the rcParam.

@manit2004
Copy link
ContributorAuthor

@rcomer I have implemented your suggestions and also added a test to verify the feature implemented.

Addedtest_legend_linewidth() to verify the new parameter's behavior across four scenarios:

  1. Direct parameter usage - Confirmsax.legend(linewidth=2.5) correctly sets the legend frame linewidth
  2. rcParam configuration - Validateslegend.linewidth rcParam is properly applied
  3. Default inheritance - EnsuresNone correctly inherits frompatch.linewidth (backward compatibility)
  4. Parameter precedence - Verifies direct parameter overrides rcParam value
rcomer reacted with thumbs up emoji

@manit2004
Copy link
ContributorAuthor

@rcomer I have renamed the .rst file and also removed those two lines as you pointed out. Is there anything else that I should do or is it ready to merge?

Copy link
Member

@rcomerrcomer left a comment

Choose a reason for hiding this comment

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

Thanks@manit2004 this looks good to me. For code changes we require two approving reviews, so now we just need to wait for someone else to take a look.

@rcomerrcomer added this to thev3.11.0 milestoneNov 23, 2025
@manit2004
Copy link
ContributorAuthor

Thanks@rcomer for guiding me through one of my first contributions in a big project like matplotlib. Waiting for the reviews.

#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?

@timhoffmtimhoffm merged commit7bf7e47 intomatplotlib:mainNov 29, 2025
39 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@timhoffmtimhoffmtimhoffm approved these changes

@rcomerrcomerrcomer approved these changes

Assignees

No one assigned

Projects

Status: Waiting for author

Milestone

v3.11.0

Development

Successfully merging this pull request may close these issues.

[ENH]: Add rcParams for the width of the legend's box edge

3 participants

@manit2004@timhoffm@rcomer

[8]ページ先頭

©2009-2025 Movatter.jp