37
37
import os
38
38
import sys
39
39
import time
40
+ import weakref
40
41
from weakref import WeakKeyDictionary
41
42
42
43
import numpy as np
@@ -1331,7 +1332,11 @@ class LocationEvent(Event):
1331
1332
The keyboard modifiers currently being pressed (except for KeyEvent).
1332
1333
"""
1333
1334
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
1335
1340
1336
1341
def __init__ (self , name , canvas , x , y , guiEvent = None , * , modifiers = None ):
1337
1342
super ().__init__ (name , canvas , guiEvent = guiEvent )
@@ -1348,20 +1353,25 @@ def __init__(self, name, canvas, x, y, guiEvent=None, *, modifiers=None):
1348
1353
# cannot check if event was in Axes if no (x, y) info
1349
1354
return
1350
1355
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.
1355
1366
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 :
1357
1370
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 ))
1360
1373
except ValueError :
1361
1374
pass
1362
- else :
1363
- self .xdata = xdata
1364
- self .ydata = ydata
1365
1375
1366
1376
1367
1377
class MouseButton (IntEnum ):
@@ -1555,17 +1565,30 @@ def _mouse_handler(event):
1555
1565
event .key = event .canvas ._key
1556
1566
# Emit axes_enter/axes_leave.
1557
1567
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
1560
1570
if last_axes != event .inaxes :
1561
1571
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.
1562
1577
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 )
1564
1585
except Exception :
1565
1586
pass # The last canvas may already have been torn down.
1566
1587
if event .inaxes is not None :
1567
1588
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 = (
1569
1592
None if event .name == "figure_leave_event" else event )
1570
1593
1571
1594
@@ -1964,8 +1987,8 @@ def leave_notify_event(self, guiEvent=None):
1964
1987
guiEvent
1965
1988
The native UI event that generated the Matplotlib event.
1966
1989
"""
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
1969
1992
self ._lastx , self ._lasty = None , None
1970
1993
1971
1994
@_api .deprecated ("3.6" , alternative = (
0 commit comments