Closed komoto48g closed 1 year ago
guiEvent is public API and would need a deprecation period; furthermore, looking at the linked wx issue, it seems like this is a bug on wx's side? Alternatively we can use the evt.__class__(evt)
hack mentioned in the thread, but "official" guidance from the wx project would be nice.
Thank you for reviewing.
it seems like this is a bug on wx's side?
I am not sure about this, so I posted this topic in [Discuss wxPython] and asked for feedback or official guidance.
Whether there is a bug involved is not yet clear. I have had a look at the C++ code, but that's very complex. There could be an issue in the wxWidgets <-> sip interaction, but that's beyond my capabilities...
Anyway, it's no good style to keep references to short lived objects. For PaintDC
it's explicitely documented that no reference is to be stored. For Event, it's not (yet) documented.
The version evt.__class__(evt)
or evt.Clone()
would care for case that someone copies guiEvent
, but I would say this is not a useful use case.
I think the best solution would be delete the reference at the end of the matplotlib event handling.
E.g. in backend_bases.py
motion_notify_event
add one of these lines at the end:
event.guiEvent = None
or:
del event.guiEvent
I would recommend the del
call.
This should be done for all Event types, even if there is currently no issue.
Unfortunately there seems to be no hook which would cover all event handlers at once.
(Adding Event.__del__
would not work.)
Thank you for taking the time to review.
The version
evt.__class__(evt)
orevt.Clone()
would care for case that someone copiesguiEvent
, but I would say this is not a useful use case.I think the best solution would be delete the reference at the end of the matplotlib event handling.
If someone holds the reference, even if del event.guiEvent
is called, it will only decrement the ref-counter.
I recognized that the behavior of wx is by design, not a bug.
I think the best solution would be to make guiEvent
API deprecated.
There are resonable reasons to make (problematic) guiEvent
API deprecated.
guiEvent
is not referenced anywhere in the matplotlib/WXAgg module, thus it has little impact.guiEvent
is not very useful because it is easy to chain the event and refer it, e.g.,
self.canvas.mpl_connect('motion_notify_event', self.on_motion_notify)
self.canvas.Bind(wx.EVT_MOTION, self.OnMotionNotify)
...
FWIW I have relied on guiEvent e.g. at https://github.com/anntzer/mplinorm/blob/f0d340b8cc63b7b000e18a466f53671ac92e7b69/lib/mplinorm.py#L163-L194. There may be workarounds but some documentation on how to achieve them would be nice (e.g. in my case I need a correspondence between the motion_notify_event handled by Matplotlib and the EVT_MOTION from wx).
I am pretty :-1: on deprecating evt.guiEvent
because that is our escape hatch to get the event from the underlying UI through to callbacks registered to Matplotlib. It is indeed a brittle API (as the type is dependent on which backend you are using), but it is still useful and present on all of the GUI backends.
The source of our problem is https://github.com/matplotlib/matplotlib/blob/96af8c52c7beb373c1970cd71916e0c6e1231db7/lib/matplotlib/backend_bases.py#L1298 and https://github.com/matplotlib/matplotlib/blob/96af8c52c7beb373c1970cd71916e0c6e1231db7/lib/matplotlib/backend_bases.py#L1332-L1356 which cache the last event as a class level attribute on Location
event when we enter / leave an Axes.
I think possible fixes here are:
LocationEvent.lastevent
(bunch of work, maybe not easy to do given that this logic is currently called from the __init__
method...maybe that should move?)LocationEvent.lastevent
and only stash the last axes?I am not a fan of deleting or setting to None
the guiEvent attribute as if the user has held onto the mpl event object, mutating it under them seems rude.
Deprecating lastevent certainly seems reasonable.
Bug summary
Scrolling the mouse wheel returns a broken xy value. After any key is pressed, the xy value will be correct during no motion.
Code for reproduction
Actual outcome
When you scroll on the canvas, you will see corrupted data such as the following:
Expected outcome
After any key is pressed (but no motion), you will see a message such as the following:
Additional information
wxPython 4.1.1 msw (phoenix) wxWidgets 3.1.5 backend_bases.py:1211: (3.5.x) backend_bases.py:1229: (3.4.x)
To fix this issue temporarily, change it to dummy data. So far,
self.guiEvent
doesn't seem to be referenced anywhere.A related issue is discussed in the Phoenix issue tracker. https://github.com/wxWidgets/Phoenix/issues/2034
Operating system
Windows 10
Matplotlib Version
3.4.0, 3.5.1
Matplotlib Backend
WXAgg
Python version
3.8.6, 3.9.9
Jupyter version
No response
Installation
pip