Skip to content

Commit 2b938cd

Browse files
authored
Merge pull request matplotlib#25101 from anntzer/le
Deprecate LocationEvent.lastevent.
2 parents 79570ab + 6bd6238 commit 2b938cd

File tree

3 files changed

+47
-17
lines changed

3 files changed

+47
-17
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Event objects emitted for ``axes_leave_event``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
``axes_leave_event`` now emits a synthetic `.LocationEvent`, instead of reusing
4+
the last event object associated with a ``motion_notify_event``.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
``LocationEvent.lastevent``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... is deprecated with no replacement.

lib/matplotlib/backend_bases.py

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import os
3838
import sys
3939
import time
40+
import weakref
4041
from weakref import WeakKeyDictionary
4142

4243
import numpy as np
@@ -1331,7 +1332,11 @@ class LocationEvent(Event):
13311332
The keyboard modifiers currently being pressed (except for KeyEvent).
13321333
"""
13331334

1334-
lastevent = None # The last event processed so far.
1335+
# Fully delete all occurrences of lastevent after deprecation elapses.
1336+
_lastevent = None
1337+
lastevent = _api.deprecated("3.8")(
1338+
_api.classproperty(lambda cls: cls._lastevent))
1339+
_last_axes_ref = None
13351340

13361341
def __init__(self, name, canvas, x, y, guiEvent=None, *, modifiers=None):
13371342
super().__init__(name, canvas, guiEvent=guiEvent)
@@ -1348,20 +1353,25 @@ def __init__(self, name, canvas, x, y, guiEvent=None, *, modifiers=None):
13481353
# cannot check if event was in Axes if no (x, y) info
13491354
return
13501355

1351-
if self.canvas.mouse_grabber is None:
1352-
self.inaxes = self.canvas.inaxes((x, y))
1353-
else:
1354-
self.inaxes = self.canvas.mouse_grabber
1356+
self._set_inaxes(self.canvas.inaxes((x, y))
1357+
if self.canvas.mouse_grabber is None else
1358+
self.canvas.mouse_grabber,
1359+
(x, y))
1360+
1361+
# Splitting _set_inaxes out is useful for the axes_leave_event handler: it
1362+
# needs to generate synthetic LocationEvents with manually-set inaxes. In
1363+
# that latter case, xy has already been cast to int so it can directly be
1364+
# read from self.x, self.y; in the normal case, however, it is more
1365+
# accurate to pass the untruncated float x, y values passed to the ctor.
13551366

1356-
if self.inaxes is not None:
1367+
def _set_inaxes(self, inaxes, xy=None):
1368+
self.inaxes = inaxes
1369+
if inaxes is not None:
13571370
try:
1358-
trans = self.inaxes.transData.inverted()
1359-
xdata, ydata = trans.transform((x, y))
1371+
self.xdata, self.ydata = inaxes.transData.inverted().transform(
1372+
xy if xy is not None else (self.x, self.y))
13601373
except ValueError:
13611374
pass
1362-
else:
1363-
self.xdata = xdata
1364-
self.ydata = ydata
13651375

13661376

13671377
class MouseButton(IntEnum):
@@ -1555,17 +1565,30 @@ def _mouse_handler(event):
15551565
event.key = event.canvas._key
15561566
# Emit axes_enter/axes_leave.
15571567
if event.name == "motion_notify_event":
1558-
last = LocationEvent.lastevent
1559-
last_axes = last.inaxes if last is not None else None
1568+
last_ref = LocationEvent._last_axes_ref
1569+
last_axes = last_ref() if last_ref else None
15601570
if last_axes != event.inaxes:
15611571
if last_axes is not None:
1572+
# Create a synthetic LocationEvent for the axes_leave_event.
1573+
# Its inaxes attribute needs to be manually set (because the
1574+
# cursor is actually *out* of that axes at that point); this is
1575+
# done with the internal _set_inaxes method which ensures that
1576+
# the xdata and ydata attributes are also correct.
15621577
try:
1563-
last.canvas.callbacks.process("axes_leave_event", last)
1578+
leave_event = LocationEvent(
1579+
"axes_leave_event", last_axes.figure.canvas,
1580+
event.x, event.y, event.guiEvent,
1581+
modifiers=event.modifiers)
1582+
leave_event._set_inaxes(last_axes)
1583+
last_axes.figure.canvas.callbacks.process(
1584+
"axes_leave_event", leave_event)
15641585
except Exception:
15651586
pass # The last canvas may already have been torn down.
15661587
if event.inaxes is not None:
15671588
event.canvas.callbacks.process("axes_enter_event", event)
1568-
LocationEvent.lastevent = (
1589+
LocationEvent._last_axes_ref = (
1590+
weakref.ref(event.inaxes) if event.inaxes else None)
1591+
LocationEvent._lastevent = (
15691592
None if event.name == "figure_leave_event" else event)
15701593

15711594

@@ -1964,8 +1987,8 @@ def leave_notify_event(self, guiEvent=None):
19641987
guiEvent
19651988
The native UI event that generated the Matplotlib event.
19661989
"""
1967-
self.callbacks.process('figure_leave_event', LocationEvent.lastevent)
1968-
LocationEvent.lastevent = None
1990+
self.callbacks.process('figure_leave_event', LocationEvent._lastevent)
1991+
LocationEvent._lastevent = None
19691992
self._lastx, self._lasty = None, None
19701993

19711994
@_api.deprecated("3.6", alternative=(

0 commit comments

Comments
 (0)