Bug report
Bug summary
When dealing with callbacks for event that are subclass of LocationEvent (KeyEvent and MouseEvent) in FigureCanvasBase methods (like motion_notify_event), an event object can be passed to callbacks.process for 'axes_enter_event' before being fully initialized. This can cause bugs.
Code for reproduction
I took the first example of the examples page and added theses lines:
def mycallback (event):
print (type(event), hasattr (event, 'button'))
print (event) # raise an exception as self.button is needed in MouseEvent.__str__
plt.gca().figure.canvas.mpl_connect ('axes_enter_event', mycallback)
Full code
import numpy as np
import matplotlib.pyplot as plt
N = 5
menMeans = (20, 35, 30, 35, 27)
womenMeans = (25, 32, 34, 20, 25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars: can also be len(x) sequence
p1 = plt.bar(ind, menMeans, width, yerr=menStd)
p2 = plt.bar(ind, womenMeans, width,
bottom=menMeans, yerr=womenStd)
plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))
def mycallback (event):
print (type(event), hasattr (event, 'button'))
print (event)
plt.gca().figure.canvas.mpl_connect ('axes_enter_event', mycallback)
plt.show()
Actual outcome
When the mouse is moved over the axes, it prints
<class 'matplotlib.backend_bases.MouseEvent'> False
Traceback (most recent call last):
File "/home/cyril/.local/lib/python3.7/site-packages/matplotlib/cbook/__init__.py", line 216, in process
func(*args, **kwargs)
File "bar_stacked.py", line 37, in mycallback
print (event)
File "/home/cyril/.local/lib/python3.7/site-packages/matplotlib/backend_bases.py", line 1445, in __str__
return (f"{self.name}: "
AttributeError: 'MouseEvent' object has no attribute 'button'
The MouseEvent object is not fully initialized (or else it would have a 'button' attribute).
The problem is due to the following calls:
- when a event is captured, the method
motion_notify_event of FigureCanvasBase is called
- it creates an MouseEvent object, so
MouseEvent.__init__ is called
- the first thing the initializer does is calling
LocationEvent.__init__ (initializer of the parent class) [ before setting self.button ]
- the last thing
LocationEvent.__init__ does is calling self._update_enter_leave
- In the method
self._update_enter_leave (of the class LocationEvent), callbacks.process is called for axes_enter_event (if mouse is in the right location) with self (a MouseEvent object) as argument for the callbacks function. The problem is here, the argument should be of LocationEvent type (according to the doc). And self cannot be use here as it is not finished being initialized.
A similar problem occurs for KeyEvent (a subclass of LocationEvent) with the attributes 'key'.
Expected outcome
According to the doc, the type of event for axes_enter_event shoud be LocationEvent not MouseEvent
Matplotlib version
- Operating system: Linux
- Matplotlib version: 3.1
- Matplotlib backend (
print(matplotlib.get_backend())): Qt5Agg
- Python version: 3.7
Bug report
Bug summary
When dealing with callbacks for event that are subclass of LocationEvent (KeyEvent and MouseEvent) in FigureCanvasBase methods (like motion_notify_event), an event object can be passed to callbacks.process for 'axes_enter_event' before being fully initialized. This can cause bugs.
Code for reproduction
I took the first example of the examples page and added theses lines:
Full code
Actual outcome
When the mouse is moved over the axes, it prints
The MouseEvent object is not fully initialized (or else it would have a 'button' attribute).
The problem is due to the following calls:
motion_notify_eventofFigureCanvasBaseis calledMouseEvent.__init__is calledLocationEvent.__init__(initializer of the parent class) [ before setting self.button ]LocationEvent.__init__does is callingself._update_enter_leaveself._update_enter_leave(of the class LocationEvent), callbacks.process is called for axes_enter_event (if mouse is in the right location) with self (a MouseEvent object) as argument for the callbacks function. The problem is here, the argument should be of LocationEvent type (according to the doc). And self cannot be use here as it is not finished being initialized.A similar problem occurs for KeyEvent (a subclass of LocationEvent) with the attributes 'key'.
Expected outcome
According to the doc, the type of event for
axes_enter_eventshoud be LocationEvent not MouseEventMatplotlib version
print(matplotlib.get_backend())): Qt5Agg