Skip to content

Commit aaa1e20

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 2f6589d commit aaa1e20

File tree

5 files changed

+221
-231
lines changed

5 files changed

+221
-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
@@ -1422,6 +1422,15 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
14221422
self.step = step
14231423
self.dblclick = dblclick
14241424

1425+
@classmethod
1426+
def _from_ax_coords(cls, name, ax, xy, *args, **kwargs):
1427+
"""Generate a synthetic event at a given axes coordinate."""
1428+
x, y = ax.transData.transform(xy)
1429+
event = cls(name, ax.figure.canvas, x, y, *args, **kwargs)
1430+
event.inaxes = ax
1431+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1432+
return event
1433+
14251434
def __str__(self):
14261435
return (f"{self.name}: "
14271436
f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
@@ -1514,6 +1523,17 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
15141523
super().__init__(name, canvas, x, y, guiEvent=guiEvent)
15151524
self.key = key
15161525

1526+
@classmethod
1527+
def _from_ax_coords(cls, name, ax, xy, key, *args, **kwargs):
1528+
"""Generate a synthetic event at a given axes coordinate."""
1529+
# Separate from MouseEvent._from_ax_coords instead of being defined in the base
1530+
# class, due to different parameter order in the constructor signature.
1531+
x, y = ax.transData.transform(xy)
1532+
event = cls(name, ax.figure.canvas, key, x, y, *args, **kwargs)
1533+
event.inaxes = ax
1534+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1535+
return event
1536+
15171537

15181538
# Default callback for key events.
15191539
def _key_handler(event):

lib/matplotlib/testing/widgets.py

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

99
from unittest import mock
1010

11+
from matplotlib.backend_bases import MouseEvent, KeyEvent
1112
import matplotlib.pyplot as plt
1213

1314

@@ -24,6 +25,7 @@ def noop(*args, **kwargs):
2425
pass
2526

2627

28+
@_api.deprecated("3.11", alternative="MouseEvent or KeyEvent")
2729
def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
2830
r"""
2931
Create a mock event that can stand in for `.Event` and its subclasses.
@@ -65,6 +67,7 @@ def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
6567
return event
6668

6769

70+
@_api.deprecated("3.11", alternative="callbacks.process(event)")
6871
def do_event(tool, etype, button=1, xdata=0, ydata=0, key=None, step=1):
6972
"""
7073
Trigger an event on the given tool.
@@ -105,15 +108,12 @@ def click_and_drag(tool, start, end, key=None):
105108
An optional key that is pressed during the whole operation
106109
(see also `.KeyEvent`).
107110
"""
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)
111+
ax = tool.ax
112+
if key is not None: # Press key
113+
KeyEvent._from_ax_coords("key_press_event", ax, start, key)._process()
112114
# 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)
115+
MouseEvent._from_ax_coords("button_press_event", ax, start, 1)._process()
116+
MouseEvent._from_ax_coords("motion_notify_event", ax, end, 1)._process()
117+
MouseEvent._from_ax_coords("button_release_event", ax, end, 1)._process()
118+
if key is not None: # Release key
119+
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