Skip to content

[Bug]: canvas.manager.set_window_title does not work to figure with WebAgg backend #29256

Closed

Description

@YongcaiHuang

Bug summary

canvas.manager.set_window_title does not work to figure with WebAgg backend (but MacOSX). the title is still Figure 1 by default.

Code for reproduction

import matplotlib.pyplot as plt
import numpy as np
import matplotlib
matplotlib.use("WebAgg")

fig = plt.figure(figsize=(7, 5))
fig.canvas.manager.set_window_title("My figure")
ax = fig.add_subplot(111)

dx, dy = 0.05, 0.05
y, x = np.mgrid[slice(1, 5 + dy, dy),
slice(1, 5 + dx, dx)]
z = np.sin(x)**10 + np.cos(10 + y*x) * np.cos(x)

cf = ax.contourf(x + dx/2., y + dy/2., z)
fig.colorbar(cf, ax=ax)

plt.show()

Actual outcome

image

Expected outcome

image

Additional information

it works in MacOSX backends

image

Operating system

macOS Sequoia 15.1.1

Matplotlib Version

3.9.3

Matplotlib Backend

WebAgg

Python version

3.12.7

Jupyter version

No response

Installation

pip

Activity

  1. ianthomas23 commented on Dec 8, 2024

    @ianthomas23
    Member

    Thanks for the report, it is an interesting bug!

    When using the webagg backend the set_window_title initially does what you want which is to update the figure_label in the browser:

    def set_window_title(self, title):
    self._send_event('figure_label', label=title)
    self._window_title = title

    However on the next render, which is essentially immediate, the figure_label is reset to the contents of figure.get_label():

    def handle_refresh(self, event):
    figure_label = self.figure.get_label()
    if not figure_label:
    figure_label = f"Figure {self.manager.num}"
    self.send_event('figure_label', label=figure_label)

    For other backends such as qtagg the use of set_window_title does indeed set the title in the title bar of the window displaying the figure, and figure.set_label() (inherited from the Artist class) is used to uniquely identify the figure and is the default filename used when saving the figure, it is not used as a visual title anywhere.

    I expect there has been some historical confusion here as webagg is different from most backends in that a figure is displayed in a browser tab and there are two possible titles here, one in the title bar of the tab and the other rendered at the top of the canvas in the page displaying the figure.

    For consistency with other backends like qtagg I think the correct behaviour is to keep the set_window_title implementation as it is and change the handle_refresh to read self._window_title rather than self.figure.get_label(). But this will change the behaviour for anyone currently using figure.set_label to change the title.

    An alternative fix is to keep the text above the figure in the web page as the figure label, and use set_window_title to set the text in the browser tab. This won't break anyone's current use of figure.set_label. AFAICT from an implementation point of view this would need another message type to be handled by lib/matplotlib/backends/web_backend/js/mpl.js which would set the document.title.

  2. QuLogic commented on Dec 10, 2024

    @QuLogic
    Member

    An alternative fix is to keep the text above the figure in the web page as the figure label, and use set_window_title to set the text in the browser tab. This won't break anyone's current use of figure.set_label. AFAICT from an implementation point of view this would need another message type to be handled by lib/matplotlib/backends/web_backend/js/mpl.js which would set the document.title.

    WebAgg supports multiple figures in a single webpage; we can't map a single figure's title to the entire document.

  3. timhoffm commented on Dec 11, 2024

    @timhoffm
    Member

    For consistency with other backends like qtagg I think the correct behaviour is to keep the set_window_title implementation as it is and change the handle_refresh to read self._window_title rather than self.figure.get_label(). But this will change the behaviour for anyone currently using figure.set_label to change the title.

    I agree, this is the way to go.

    AFAICS, the meaning of Figure.set_label is not documented anywhere. Technically it's inherited from Artist.set_label, which refers to legend labels. We have some internal code that repurposes it for figure, but that's not documented. More generally, label is a heavily overloaded term and we should try to use it less. Semi-related: #28584, where we disallowed Axis.set_label as that was also causing confusion.

  4. ianthomas23 commented on Dec 11, 2024

    @ianthomas23
    Member

    Thanks @QuLogic and @timhoffm for the clarification. I should be able to come up a PR for this soon.

  5. added this to the v3.11.0 milestone on Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions