8000 Bind subplot_tool more closely to target figure. · matplotlib/matplotlib@7ae3c1d · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ae3c1d

Browse files
committed
Bind subplot_tool more closely to target figure.
- More the implementation to backend_bases and have pyplot read it, rather than having backend_bases fetch it from pyplot, which was a bit weird. - Attach the subplot_tool to the toolbar, which avoids having to keep a reference to it (when calling plt.subplot_tool), and prevents opening two subplot_tools for the same figure. On most backends, closing the subplot_tool deletes the reference, because reopening a closed figure seems not guaranteed to work; on Qt, which has its own subplot_tool, reopening the closed QDialog does work, so just reuse it. - Ensure that closing the main figure also closes the subplot_tool.
1 parent 552e078 commit 7ae3c1d

File tree

3 files changed

+45
-21
lines changed

3 files changed

+45
-21
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,9 +3258,24 @@ def _update_view(self):
32583258
self.canvas.draw_idle()
32593259

32603260
def configure_subplots(self, *args):
3261+
if hasattr(self, "subplot_tool"):
3262+
self.subplot_tool.figure.canvas.manager.show()
3263+
return
32613264
plt = _safe_pyplot_import()
3262-
self.subplot_tool = plt.subplot_tool(self.canvas.figure)
3263-
self.subplot_tool.figure.canvas.manager.show()
3265+
with mpl.rc_context({"toolbar": "none"}): # No navbar for the toolfig.
3266+
# Use new_figure_manager() instead of figure() so that the figure
3267+
# doesn't get registered with pyplot.
3268+
manager = plt.new_figure_manager(-1, (6, 3))
3269+
manager.set_window_title("Subplot configuration tool")
3270+
tool_fig = manager.canvas.figure
3271+
tool_fig.subplots_adjust(top=0.9)
3272+
self.subplot_tool = widgets.SubplotTool(self.canvas.figure, tool_fig)
3273+
tool_fig.canvas.mpl_connect(
3274+
"close_event", lambda e: delattr(self, "subplot_tool"))
3275+
self.canvas.mpl_connect(
3276+
"close_event", lambda e: manager.destroy())
3277+
manager.show()
3278+
return self.subplot_tool
32643279

32653280
def save_figure(self, *args):
32663281
"""Save the current figure."""

lib/matplotlib/backends/backend_qt.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,14 @@ def remove_rubberband(self):
750750
self.canvas.drawRectangle(None)
751751

752752
def configure_subplots(self):
753-
image = str(cbook._get_data_path('images/matplotlib.png'))
754-
self._subplot_dialog = SubplotToolQt(
755-
self.canvas.figure, self.canvas.parent())
756-
self._subplot_dialog.setWindowIcon(QtGui.QIcon(image))
753+
if self._subplot_dialog is None:
754+
self._subplot_dialog = SubplotToolQt(
755+
self.canvas.figure, self.canvas.parent())
756+
self.canvas.mpl_connect(
757+
"close_event", lambda e: self._subplot_dialog.reject())
758+
self._subplot_dialog.update_from_current_subplotpars()
757759
self._subplot_dialog.show()
760+
return self._subplot_dialog
758761

759762
def save_figure(self, *args):
760763
filetypes = self.canvas.get_supported_filetypes_grouped()
@@ -799,6 +802,8 @@ def set_history_buttons(self):
799802
class SubplotToolQt(QtWidgets.QDialog):
800803
def __init__(self, targetfig, parent):
801804
super().__init__()
805+
self.setWindowIcon(QtGui.QIcon(
806+
str(cbook._get_data_path("images/matplotlib.png"))))
802807
self.setObjectName("SubplotTool")
803808
self._spinboxes = {}
804809
main_layout = QtWidgets.QHBoxLayout()
@@ -819,7 +824,6 @@ def __init__(self, targetfig, parent):
819824
inner = QtWidgets.QFormLayout(box)
820825
for name in spinboxes:
821826
self._spinboxes[name] = spinbox = QtWidgets.QDoubleSpinBox()
822-
spinbox.setValue(getattr(targetfig.subplotpars, name))
823827
spinbox.setRange(0, 1)
824828
spinbox.setDecimals(3)
825829
spinbox.setSingleStep(0.005)
@@ -836,9 +840,14 @@ def __init__(self, targetfig, parent):
836840
if name == "Close":
837841
button.setFocus()
838842
self._figure = targetfig
839-
self._defaults = {spinbox: vars(self._figure.subplotpars)[attr]
840-
for attr, spinbox in self._spinboxes.items()}
843+
self._defaults = {}
841844
self._export_values_dialog = None
845+
self.update_from_current_subplotpars()
846+
847+
def update_from_current_subplotpars(self):
848+
self._defaults = {spinbox: getattr(self._figure.subplotpars, name)
849+
for name, spinbox in self._spinboxes.items()}
850+
self._reset() # Set spinbox current values without triggering signals.
842851

843852
def _export_values(self):
844853
# Explicitly round to 3 decimals (which is also the spinbox precision)

lib/matplotlib/pyplot.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
from matplotlib.lines import Line2D
7575
from matplotlib.text import Text, Annotation
7676
from matplotlib.patches import Polygon, Rectangle, Circle, Arrow
77-
from matplotlib.widgets import SubplotTool, Button, Slider, Widget
77+
from matplotlib.widgets import Button, Slider, Widget
7878

7979
from .ticker import (
8080
TickHelper, Formatter, FixedFormatter, NullFormatter, FuncFormatter,
@@ -1627,20 +1627,20 @@ def subplot_tool(targetfig=None):
16271627
"""
16281628
Launch a subplot tool window for a figure.
16291629
1630-
A `matplotlib.widgets.SubplotTool` instance is returned. You must maintain
1631-
a reference to the instance to keep the associated callbacks alive.
1630+
Returns
1631+
-------
1632+
`matplotlib.widgets.SubplotTool`
16321633
"""
16331634
if targetfig is None:
16341635
targetfig = gcf()
1635-
with rc_context({"toolbar": "none"}): # No navbar for the toolfig.
1636-
# Use new_figure_manager() instead of figure() so that the figure
1637-
# doesn't get registered with pyplot.
1638-
manager = new_figure_manager(-1, (6, 3))
1639-
manager.set_window_title("Subplot configuration tool")
1640-
tool_fig = manager.canvas.figure
1641-
tool_fig.subplots_adjust(top=0.9)
1642-
manager.show()
1643-
return SubplotTool(targetfig, tool_fig)
1636+
tb = targetfig.canvas.manager.toolbar
1637+
if hasattr(tb, "configure_subplots"): # toolbar2
1638+
return tb.configure_subplots()
1639+
elif hasattr(tb, "trigger_tool"): # toolmanager
1640+
return tb.trigger_tool("subplots")
1641+
else:
1642+
raise ValueError("subplot_tool can only be launched for figures with "
1643+
"an associated toolbar")
16441644

16451645

16461646
def box(on=None):

0 commit comments

Comments
 (0)
0