Skip to content

Commit ee0081d

Browse files
committed
Trigger events via standard callbacks in widget testing.
Sending actual events through the whole event processing pipeline is a more complete test, reveals a few minor issues (see changes below), and avoids being linked to the rather nonstandard widget method names ("press" or "_click"?). The coordinates in the "move first vertex after completing the polygon" subtest of test_polygon_selector(draw_bounding_box=True) were altered because the original coordinates would actually not work in a real case, as the mouse-drag would actually also trigger the polygon-rescaling behavior. The coordinates in test_rectangle_{drag,resize} were altered because for the original coordinates, the click_and_drag would actually be ignore()d due to starting (just) outside of the axes.
1 parent bff64cc commit ee0081d

File tree

5 files changed

+222
-231
lines changed

5 files changed

+222
-231
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``testing.widgets.mock_event`` and ``testing.widgets.do_event``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... are deprecated. Directly construct Event objects (typically `.MouseEvent`
4+
or `.KeyEvent`) and pass them to ``canvas.callbacks.process()`` instead.

lib/matplotlib/backend_bases.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,15 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
14111411
self.step = step
14121412
self.dblclick = dblclick
14131413

1414+
@classmethod
1415+
def _from_ax_coords(cls, name, ax, xy, *args, **kwargs):
1416+
"""Generate a synthetic event at a given axes coordinate."""
1417+
x, y = ax.transData.transform(xy)
1418+
event = cls(name, ax.figure.canvas, x, y, *args, **kwargs)
1419+
event.inaxes = ax
1420+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1421+
return event
1422+
14141423
def __str__(self):
14151424
return (f"{self.name}: "
14161425
f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
@@ -1503,6 +1512,17 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
15031512
super().__init__(name, canvas, x, y, guiEvent=guiEvent)
15041513
self.key = key
15051514

1515+
@classmethod
1516+
def _from_ax_coords(cls, name, ax, xy, key, *args, **kwargs):
1517+
"""Generate a synthetic event at a given axes coordinate."""
1518+
# Separate from MouseEvent._from_ax_coords instead of being defined in the base
1519+
# class, due to different parameter order in the constructor signature.
1520+
x, y = ax.transData.transform(xy)
1521+
event = cls(name, ax.figure.canvas, key, x, y, *args, **kwargs)
1522+
event.inaxes = ax
1523+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1524+
return event
1525+
15061526

15071527
# Default callback for key events.
15081528
def _key_handler(event):

lib/matplotlib/testing/widgets.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
from unittest import mock
1010

11+
from matplotlib import _api
12+
from matplotlib.backend_bases import MouseEvent, KeyEvent
1113
import matplotlib.pyplot as plt
1214

1315

@@ -24,6 +26,7 @@ def noop(*args, **kwargs):
2426
pass
2527

2628

29+
@_api.deprecated("3.11", alternative="MouseEvent or KeyEvent")
2730
def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
2831
r"""
2932
Create a mock event that can stand in for `.Event` and its subclasses.
@@ -65,6 +68,7 @@ def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
6568
return event
6669

6770

71+
@_api.deprecated("3.11", alternative="callbacks.process(event)")
6872
def do_event(tool, etype, button=1, xdata=0, ydata=0, key=None, step=1):
6973
"""
7074
Trigger an event on the given tool.
@@ -105,15 +109,12 @@ def click_and_drag(tool, start, end, key=None):
105109
An optional key that is pressed during the whole operation
106110
(see also `.KeyEvent`).
107111
"""
108-
if key is not None:
109-
# Press key
110-
do_event(tool, 'on_key_press', xdata=start[0], ydata=start[1],
111-
button=1, key=key)
112+
ax = tool.ax
113+
if key is not None: # Press key
114+
KeyEvent._from_ax_coords("key_press_event", ax, start, key)._process()
112115
# Click, move, and release mouse
113-
do_event(tool, 'press', xdata=start[0], ydata=start[1], button=1)
114-
do_event(tool, 'onmove', xdata=end[0], ydata=end[1], button=1)
115-
do_event(tool, 'release', xdata=end[0], ydata=end[1], button=1)
116-
if key is not None:
117-
# Release key
118-
do_event(tool, 'on_key_release', xdata=end[0], ydata=end[1],
119-
button=1, key=key)
116+
MouseEvent._from_ax_coords("button_press_event", ax, start, 1)._process()
117+
MouseEvent._from_ax_coords("motion_notify_event", ax, end, 1)._process()
118+
MouseEvent._from_ax_coords("button_release_event", ax, end, 1)._process()
119+
if key is not None: # Release key
120+
KeyEvent._from_ax_coords("key_release_event", ax, end, key)._process()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy