diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 7f2ab50a56b2..027baa36b68c 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -3537,6 +3537,43 @@ def new_figure_manager_given_figure(cls, num, figure): manager = cls.FigureManager(canvas, num) return manager + @classmethod + def new_figure(cls, label='Matplotlib Figure', *, + auto_redraw=True, auto_show=True): + """ + Create a new window with a Figure and toolbar + + Parameters + ---------- + label : str + Use for the window title and figure label. + + auto_redraw : bool + If the figure should automatically re-draw when stale. + + auto_show : bool + If the GUI window should be shown on creation. + """ + manager = cls.new_figure_manager(label) + manager.canvas.figure.set_label(label) + + def redraw(fig, val): + canvas = fig.canvas + if val and not canvas.is_saving() and not canvas._is_idle_drawing: + # Some artists can mark themselves as stale in the + # middle of drawing (e.g. axes position & tick labels + # being computed at draw time), but this shouldn't + # trigger a redraw because the current redraw will + # already take them into account. + with fig.canvas._idle_draw_cntx(): + fig.canvas.draw_idle() + + if auto_redraw: + manager.canvas.figure.stale_callback = redraw + if auto_show: + manager.show() + return manager.canvas.figure + @classmethod def draw_if_interactive(cls): if cls.trigger_manager_draw is not None and is_interactive(): @@ -3590,6 +3627,7 @@ def export(cls): "FigureManager", "new_figure_manager", "new_figure_manager_given_figure", + "new_figure", "draw_if_interactive", "show", ]: diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 69b57fc15d2a..cf422e87eac1 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -348,7 +348,11 @@ def __init__(self, canvas, num, window): super().__init__(canvas, num) self.window = window self.window.withdraw() - self.set_window_title("Figure %d" % num) + if isinstance(num, str): + title = num + else: + title = f"Figure {num}" + self.set_window_title(title) # packing toolbar first, because if space is getting low, last packed # widget is getting shrunk first (-> the canvas) self.toolbar = self._get_toolbar() diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 7587004fc685..35ab2aff2b40 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -316,7 +316,11 @@ def __init__(self, canvas, num): self.window = Gtk.Window() self.window.set_wmclass("matplotlib", "Matplotlib") - self.set_window_title("Figure %d" % num) + if isinstance(num, str): + title = num + else: + title = f"Figure {num}" + self.set_window_title(title) try: self.window.set_icon_from_file(window_icon) except Exception: diff --git a/lib/matplotlib/backends/backend_macosx.py b/lib/matplotlib/backends/backend_macosx.py index ea02d7cca484..cf669f5a9b1a 100644 --- a/lib/matplotlib/backends/backend_macosx.py +++ b/lib/matplotlib/backends/backend_macosx.py @@ -88,7 +88,10 @@ class FigureManagerMac(_macosx.FigureManager, FigureManagerBase): """ def __init__(self, canvas, num): FigureManagerBase.__init__(self, canvas, num) - title = "Figure %d" % num + if isinstance(num, str): + title = num + else: + title = f"Figure {num}" _macosx.FigureManager.__init__(self, canvas, title) if mpl.rcParams['toolbar'] == 'toolbar2': self.toolbar = NavigationToolbar2Mac(canvas) diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 162af99f0efa..97392793d2cb 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -534,8 +534,11 @@ def __init__(self, canvas, num): self.window = MainWindow() self.window.closing.connect(canvas.close_event) self.window.closing.connect(self._widgetclosed) - - self.window.setWindowTitle("Figure %d" % num) + if isinstance(num, str): + title = num + else: + title = f"Figure {num}" + self.window.setWindowTitle(title) image = str(cbook._get_data_path('images/matplotlib.svg')) self.window.setWindowIcon(QtGui.QIcon(image)) diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index d8016e537563..d6d7d8b90b92 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -298,7 +298,7 @@ def handle_toolbar_button(self, event): def handle_refresh(self, event): figure_label = self.figure.get_label() if not figure_label: - figure_label = "Figure {0}".format(self.manager.num) + figure_label = self._title self.send_event('figure_label', label=figure_label) self._force_full = True if self.toolbar: @@ -410,7 +410,10 @@ class FigureManagerWebAgg(backend_bases.FigureManagerBase): def __init__(self, canvas, num): super().__init__(canvas, num) - + if isinstance(num, str): + self._title = num + else: + self._title = f"Figure {num}" self.web_sockets = set() self.toolbar = self._get_toolbar(canvas) @@ -429,6 +432,7 @@ def resize(self, w, h, forward=True): forward=forward) def set_window_title(self, title): + self._title = title self._send_event('figure_label', label=title) # The following methods are specific to FigureManagerWebAgg diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 8d2083d555e5..8f7bb8ee157c 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -902,7 +902,11 @@ def __init__(self, num, fig): pos = wx.DefaultPosition else: pos = wx.Point(20, 20) - super().__init__(parent=None, id=-1, pos=pos, title="Figure %d" % num) + if isinstance(num, str): + title = num + else: + title = f"Figure {num}" + super().__init__(parent=None, id=-1, pos=pos, title=title) # Frame will be sized later by the Fit method _log.debug("%s - __init__()", type(self)) self.num = num