From 733fbb092e1fd5ed9c0ea21fbddcffcfa32c738f Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 24 Mar 2021 03:23:20 -0400 Subject: [PATCH 1/2] Deprecate access to Cursor/MultiCursor event handlers. --- .../deprecations/19763-ES.rst | 5 ++++ lib/matplotlib/tests/test_widgets.py | 4 ++-- lib/matplotlib/widgets.py | 24 ++++++++++++------- 3 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 doc/api/next_api_changes/deprecations/19763-ES.rst diff --git a/doc/api/next_api_changes/deprecations/19763-ES.rst b/doc/api/next_api_changes/deprecations/19763-ES.rst new file mode 100644 index 000000000000..6df1b0abaa75 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/19763-ES.rst @@ -0,0 +1,5 @@ +``Cursor`` and ``MultiCursor`` event handlers are now private +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Access to the event handlers for the `.Cursor` and `.MultiCursor` widgets is +now deprecated. diff --git a/lib/matplotlib/tests/test_widgets.py b/lib/matplotlib/tests/test_widgets.py index 4e1455660da9..f09c7ab4b3b6 100644 --- a/lib/matplotlib/tests/test_widgets.py +++ b/lib/matplotlib/tests/test_widgets.py @@ -1517,7 +1517,7 @@ def test_MultiCursor(horizOn, vertOn): # Can't use `do_event` as that helper requires the widget # to have a single .ax attribute. event = mock_event(ax1, xdata=.5, ydata=.25) - multi.onmove(event) + multi._onmove(event) # the lines in the first two ax should both move for l in multi.vlines: @@ -1528,7 +1528,7 @@ def test_MultiCursor(horizOn, vertOn): # test a move event in an Axes not part of the MultiCursor # the lines in ax1 and ax2 should not have moved. event = mock_event(ax3, xdata=.75, ydata=.75) - multi.onmove(event) + multi._onmove(event) for l in multi.vlines: assert l.get_xdata() == (.5, .5) for l in multi.hlines: diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 24a5bcad98d5..977c2154149e 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1600,8 +1600,8 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, **lineprops): super().__init__(ax) - self.connect_event('motion_notify_event', self.onmove) - self.connect_event('draw_event', self.clear) + self.connect_event('motion_notify_event', self._onmove) + self.connect_event('draw_event', self._clear) self.visible = True self.horizOn = horizOn @@ -1616,7 +1616,9 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, self.background = None self.needclear = False - def clear(self, event): + clear = _api.deprecate_privatize_attribute('3.5') + + def _clear(self, event): """Internal event handler to clear the cursor.""" if self.ignore(event): return @@ -1625,7 +1627,9 @@ def clear(self, event): self.linev.set_visible(False) self.lineh.set_visible(False) - def onmove(self, event): + onmove = _api.deprecate_privatize_attribute('3.5') + + def _onmove(self, event): """Internal event handler to draw the cursor when the mouse moves.""" if self.ignore(event): return @@ -1749,8 +1753,8 @@ def connect(self): """Connect events.""" for canvas, info in self._canvas_infos.items(): info["cids"] = [ - canvas.mpl_connect('motion_notify_event', self.onmove), - canvas.mpl_connect('draw_event', self.clear), + canvas.mpl_connect('motion_notify_event', self._onmove), + canvas.mpl_connect('draw_event', self._clear), ] def disconnect(self): @@ -1760,7 +1764,9 @@ def disconnect(self): canvas.mpl_disconnect(cid) info["cids"].clear() - def clear(self, event): + clear = _api.deprecate_privatize_attribute('3.5') + + def _clear(self, event): """Clear the cursor.""" if self.ignore(event): return @@ -1770,7 +1776,9 @@ def clear(self, event): for line in self.vlines + self.hlines: line.set_visible(False) - def onmove(self, event): + onmove = _api.deprecate_privatize_attribute('3.5') + + def _onmove(self, event): if (self.ignore(event) or event.inaxes not in self.axes or not event.canvas.widgetlock.available(self)): From 44405a03e60ad4c468f6d0143c45c86b5dbc0d54 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 24 Mar 2021 03:52:42 -0400 Subject: [PATCH 2/2] Remove visibility changes in draw for *Cursor widgets. This can be all handled in the mouse move event handler instead, and prevents triggering extra draws in nbAgg. Fixes #19633. --- lib/matplotlib/widgets.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 977c2154149e..a909b856951e 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -1616,7 +1616,14 @@ def __init__(self, ax, horizOn=True, vertOn=True, useblit=False, self.background = None self.needclear = False - clear = _api.deprecate_privatize_attribute('3.5') + @_api.deprecated('3.5') + def clear(self, event): + """Internal event handler to clear the cursor.""" + self._clear(event) + if self.ignore(event): + return + self.linev.set_visible(False) + self.lineh.set_visible(False) def _clear(self, event): """Internal event handler to clear the cursor.""" @@ -1624,8 +1631,6 @@ def _clear(self, event): return if self.useblit: self.background = self.canvas.copy_from_bbox(self.ax.bbox) - self.linev.set_visible(False) - self.lineh.set_visible(False) onmove = _api.deprecate_privatize_attribute('3.5') @@ -1644,15 +1649,15 @@ def _onmove(self, event): self.needclear = False return self.needclear = True - if not self.visible: - return + self.linev.set_xdata((event.xdata, event.xdata)) + self.linev.set_visible(self.visible and self.vertOn) self.lineh.set_ydata((event.ydata, event.ydata)) - self.linev.set_visible(self.visible and self.vertOn) self.lineh.set_visible(self.visible and self.horizOn) - self._update() + if self.visible and (self.vertOn or self.horizOn): + self._update() def _update(self): if self.useblit: @@ -1764,7 +1769,14 @@ def disconnect(self): canvas.mpl_disconnect(cid) info["cids"].clear() - clear = _api.deprecate_privatize_attribute('3.5') + @_api.deprecated('3.5') + def clear(self, event): + """Clear the cursor.""" + if self.ignore(event): + return + self._clear(event) + for line in self.vlines + self.hlines: + line.set_visible(False) def _clear(self, event): """Clear the cursor.""" @@ -1773,8 +1785,6 @@ def _clear(self, event): if self.useblit: for canvas, info in self._canvas_infos.items(): info["background"] = canvas.copy_from_bbox(canvas.figure.bbox) - for line in self.vlines + self.hlines: - line.set_visible(False) onmove = _api.deprecate_privatize_attribute('3.5') @@ -1784,8 +1794,6 @@ def _onmove(self, event): or not event.canvas.widgetlock.available(self)): return self.needclear = True - if not self.visible: - return if self.vertOn: for line in self.vlines: line.set_xdata((event.xdata, event.xdata)) @@ -1794,7 +1802,8 @@ def _onmove(self, event): for line in self.hlines: line.set_ydata((event.ydata, event.ydata)) line.set_visible(self.visible) - self._update() + if self.visible and (self.vertOn or self.horizOn): + self._update() def _update(self): if self.useblit: