@@ -1220,11 +1220,16 @@ class Event:
12201220 guiEvent
12211221 The GUI event that triggered the Matplotlib event.
12221222 """
1223+
12231224 def __init__ (self , name , canvas , guiEvent = None ):
12241225 self .name = name
12251226 self .canvas = canvas
12261227 self .guiEvent = guiEvent
12271228
1229+ def _process (self ):
1230+ """Generate an event with name ``self.name`` on ``self.canvas``."""
1231+ self .canvas .callbacks .process (self .name , self )
1232+
12281233
12291234class DrawEvent (Event ):
12301235 """
@@ -1267,14 +1272,28 @@ class ResizeEvent(Event):
12671272 height : int
12681273 Height of the canvas in pixels.
12691274 """
1275+
12701276 def __init__ (self , name , canvas ):
12711277 super ().__init__ (name , canvas )
12721278 self .width , self .height = canvas .get_width_height ()
12731279
1280+ def _process (self ):
1281+ super ()._process ()
1282+ self .canvas .draw_idle ()
1283+
12741284
12751285class CloseEvent (Event ):
12761286 """An event triggered by a figure being closed."""
12771287
1288+ def _process (self ):
1289+ try :
1290+ super ()._process ()
1291+ except (AttributeError , TypeError ):
1292+ pass
1293+ # Suppress AttributeError/TypeError that occur when the python
1294+ # session is being killed. It may be that a better solution would
1295+ # be a mechanism to disconnect all callbacks upon shutdown.
1296+
12781297
12791298class LocationEvent (Event ):
12801299 """
@@ -1294,7 +1313,7 @@ class LocationEvent(Event):
12941313 is not over an Axes.
12951314 """
12961315
1297- lastevent = None # the last event that was triggered before this one
1316+ lastevent = None # The last event processed so far.
12981317
12991318 def __init__ (self , name , canvas , x , y , guiEvent = None ):
13001319 super ().__init__ (name , canvas , guiEvent = guiEvent )
@@ -1308,7 +1327,6 @@ def __init__(self, name, canvas, x, y, guiEvent=None):
13081327
13091328 if x is None or y is None :
13101329 # cannot check if event was in Axes if no (x, y) info
1311- self ._update_enter_leave ()
13121330 return
13131331
13141332 if self .canvas .mouse_grabber is None :
@@ -1326,33 +1344,21 @@ def __init__(self, name, canvas, x, y, guiEvent=None):
13261344 self .xdata = xdata
13271345 self .ydata = ydata
13281346
1329- self ._update_enter_leave ()
1330-
1331- def _update_enter_leave (self ):
1332- """Process the figure/axes enter leave events."""
1333- if LocationEvent .lastevent is not None :
1334- last = LocationEvent .lastevent
1335- if last .inaxes != self .inaxes :
1336- # process Axes enter/leave events
1347+ def _process (self ):
1348+ last = LocationEvent .lastevent
1349+ last_axes = last .inaxes if last is not None else None
1350+ if last_axes != self .inaxes :
1351+ if last_axes is not None :
13371352 try :
1338- if last .inaxes is not None :
1339- last .canvas .callbacks .process ('axes_leave_event' , last )
1353+ last .canvas .callbacks .process ("axes_leave_event" , last )
13401354 except Exception :
1355+ # The last canvas may already have been torn down.
13411356 pass
1342- # See ticket 2901582.
1343- # I think this is a valid exception to the rule
1344- # against catching all exceptions; if anything goes
1345- # wrong, we simply want to move on and process the
1346- # current event.
1347- if self .inaxes is not None :
1348- self .canvas .callbacks .process ('axes_enter_event' , self )
1349-
1350- else :
1351- # process a figure enter event
13521357 if self .inaxes is not None :
1353- self .canvas .callbacks .process ('axes_enter_event' , self )
1354-
1355- LocationEvent .lastevent = self
1358+ self .canvas .callbacks .process ("axes_enter_event" , self )
1359+ LocationEvent .lastevent = (
1360+ None if self .name == "figure_leave_event" else self )
1361+ super ()._process ()
13561362
13571363
13581364class MouseButton (IntEnum ):
@@ -1375,11 +1381,15 @@ class MouseEvent(LocationEvent):
13751381 ----------
13761382 button : None or `MouseButton` or {'up', 'down'}
13771383 The button pressed. 'up' and 'down' are used for scroll events.
1384+
13781385 Note that LEFT and RIGHT actually refer to the "primary" and
13791386 "secondary" buttons, i.e. if the user inverts their left and right
13801387 buttons ("left-handed setting") then the LEFT button will be the one
13811388 physically on the right.
13821389
1390+ If this is unset, *name* is "scroll_event", and *step* is nonzero, then
1391+ this will be set to "up" or "down" depending on the sign of *step*.
1392+
13831393 key : None or str
13841394 The key pressed when the mouse event triggered, e.g. 'shift'.
13851395 See `KeyEvent`.
@@ -1413,6 +1423,11 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
14131423 step = 0 , dblclick = False , guiEvent = None ):
14141424 if button in MouseButton .__members__ .values ():
14151425 button = MouseButton (button )
1426+ if name == "scroll_event" and button is None :
1427+ if step > 0 :
1428+ button = "up"
1429+ elif step < 0 :
1430+ button = "down"
14161431 self .button = button
14171432 self .key = key
14181433 self .step = step
@@ -1422,6 +1437,17 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
14221437 # 'axes_enter_event', which requires a fully initialized event.
14231438 super ().__init__ (name , canvas , x , y , guiEvent = guiEvent )
14241439
1440+ def _process (self ):
1441+ if self .name == "button_press_event" :
1442+ self .canvas ._button = self .button
1443+ elif self .name == "button_release_event" :
1444+ self .canvas ._button = None
1445+ elif self .name == "motion_notify_event" and self .button is None :
1446+ self .button = self .canvas ._button
1447+ if self .key is None :
1448+ self .key = self .canvas ._key
1449+ super ()._process ()
1450+
14251451 def __str__ (self ):
14261452 return (f"{ self .name } : "
14271453 f"xy=({ self .x } , { self .y } ) xydata=({ self .xdata } , { self .ydata } ) "
@@ -1467,8 +1493,11 @@ def on_pick(event):
14671493
14681494 cid = fig.canvas.mpl_connect('pick_event', on_pick)
14691495 """
1496+
14701497 def __init__ (self , name , canvas , mouseevent , artist ,
14711498 guiEvent = None , ** kwargs ):
1499+ if guiEvent is None :
1500+ guiEvent = mouseevent .guiEvent
14721501 super ().__init__ (name , canvas , guiEvent )
14731502 self .mouseevent = mouseevent
14741503 self .artist = artist
@@ -1506,11 +1535,19 @@ def on_key(event):
15061535
15071536 cid = fig.canvas.mpl_connect('key_press_event', on_key)
15081537 """
1538+
15091539 def __init__ (self , name , canvas , key , x = 0 , y = 0 , guiEvent = None ):
15101540 self .key = key
15111541 # super-init deferred to the end: callback errors if called before
15121542 super ().__init__ (name , canvas , x , y , guiEvent = guiEvent )
15131543
1544+ def _process (self ):
1545+ if self .name == "key_press_event" :
1546+ self .canvas ._key = self .key
1547+ elif self .name == "key_release_event" :
1548+ self .canvas ._key = None
1549+ super ()._process ()
1550+
15141551
15151552def _get_renderer (figure , print_method = None ):
15161553 """
@@ -1720,12 +1757,16 @@ def resize(self, w, h):
17201757 _api .warn_deprecated ("3.6" , name = "resize" , obj_type = "method" ,
17211758 alternative = "FigureManagerBase.resize" )
17221759
1760+ @_api .deprecated ("3.6" , alternative = (
1761+ "callbacks.process('draw_event', DrawEvent(...))" ))
17231762 def draw_event (self , renderer ):
17241763 """Pass a `DrawEvent` to all functions connected to ``draw_event``."""
17251764 s = 'draw_event'
17261765 event = DrawEvent (s , self , renderer )
17271766 self .callbacks .process (s , event )
17281767
1768+ @_api .deprecated ("3.6" , alternative = (
1769+ "callbacks.process('resize_event', ResizeEvent(...))" ))
17291770 def resize_event (self ):
17301771 """
17311772 Pass a `ResizeEvent` to all functions connected to ``resize_event``.
@@ -1735,6 +1776,8 @@ def resize_event(self):
17351776 self .callbacks .process (s , event )
17361777 self .draw_idle ()
17371778
1779+ @_api .deprecated ("3.6" , alternative = (
1780+ "callbacks.process('close_event', CloseEvent(...))" ))
17381781 def close_event (self , guiEvent = None ):
17391782 """
17401783 Pass a `CloseEvent` to all functions connected to ``close_event``.
@@ -1751,6 +1794,8 @@ def close_event(self, guiEvent=None):
17511794 # AttributeError occurs on OSX with qt4agg upon exiting
17521795 # with an open window; 'callbacks' attribute no longer exists.
17531796
1797+ @_api .deprecated ("3.6" , alternative = (
1798+ "callbacks.process('key_press_event', KeyEvent(...))" ))
17541799 def key_press_event (self , key , guiEvent = None ):
17551800 """
17561801 Pass a `KeyEvent` to all functions connected to ``key_press_event``.
@@ -1761,6 +1806,8 @@ def key_press_event(self, key, guiEvent=None):
17611806 s , self , key , self ._lastx , self ._lasty , guiEvent = guiEvent )
17621807 self .callbacks .process (s , event )
17631808
1809+ @_api .deprecated ("3.6" , alternative = (
1810+ "callbacks.process('key_release_event', KeyEvent(...))" ))
17641811 def key_release_event (self , key , guiEvent = None ):
17651812 """
17661813 Pass a `KeyEvent` to all functions connected to ``key_release_event``.
@@ -1771,6 +1818,8 @@ def key_release_event(self, key, guiEvent=None):
17711818 self .callbacks .process (s , event )
17721819 self ._key = None
17731820
1821+ @_api .deprecated ("3.6" , alternative = (
1822+ "callbacks.process('pick_event', PickEvent(...))" ))
17741823 def pick_event (self , mouseevent , artist , ** kwargs ):
17751824 """
17761825 Callback processing for pick events.
@@ -1787,6 +1836,8 @@ def pick_event(self, mouseevent, artist, **kwargs):
17871836 ** kwargs )
17881837 self .callbacks .process (s , event )
17891838
1839+ @_api .deprecated ("3.6" , alternative = (
1840+ "callbacks.process('scroll_event', MouseEvent(...))" ))
17901841 def scroll_event (self , x , y , step , guiEvent = None ):
17911842 """
17921843 Callback processing for scroll events.
@@ -1807,6 +1858,8 @@ def scroll_event(self, x, y, step, guiEvent=None):
18071858 step = step , guiEvent = guiEvent )
18081859 self .callbacks .process (s , mouseevent )
18091860
1861+ @_api .deprecated ("3.6" , alternative = (
1862+ "callbacks.process('button_press_event', MouseEvent(...))" ))
18101863 def button_press_event (self , x , y , button , dblclick = False , guiEvent = None ):
18111864 """
18121865 Callback processing for mouse button press events.
@@ -1824,6 +1877,8 @@ def button_press_event(self, x, y, button, dblclick=False, guiEvent=None):
18241877 dblclick = dblclick , guiEvent = guiEvent )
18251878 self .callbacks .process (s , mouseevent )
18261879
1880+ @_api .deprecated ("3.6" , alternative = (
1881+ "callbacks.process('button_release_event', MouseEvent(...))" ))
18271882 def button_release_event (self , x , y , button , guiEvent = None ):
18281883 """
18291884 Callback processing for mouse button release events.
@@ -1848,6 +1903,9 @@ def button_release_event(self, x, y, button, guiEvent=None):
18481903 self .callbacks .process (s , event )
18491904 self ._button = None
18501905
1906+ # Also remove _lastx, _lasty when this goes away.
1907+ @_api .deprecated ("3.6" , alternative = (
1908+ "callbacks.process('motion_notify_event', MouseEvent(...))" ))
18511909 def motion_notify_event (self , x , y , guiEvent = None ):
18521910 """
18531911 Callback processing for mouse movement events.
@@ -1873,6 +1931,8 @@ def motion_notify_event(self, x, y, guiEvent=None):
18731931 guiEvent = guiEvent )
18741932 self .callbacks .process (s , event )
18751933
1934+ @_api .deprecated ("3.6" , alternative = (
1935+ "callbacks.process('leave_notify_event', LocationEvent(...))" ))
18761936 def leave_notify_event (self , guiEvent = None ):
18771937 """
18781938 Callback processing for the mouse cursor leaving the canvas.
@@ -1889,6 +1949,8 @@ def leave_notify_event(self, guiEvent=None):
18891949 LocationEvent .lastevent = None
18901950 self ._lastx , self ._lasty = None , None
18911951
1952+ @_api .deprecated ("3.6" , alternative = (
1953+ "callbacks.process('enter_notify_event', LocationEvent(...))" ))
18921954 def enter_notify_event (self , guiEvent = None , xy = None ):
18931955 """
18941956 Callback processing for the mouse cursor entering the canvas.
0 commit comments