8000 Trigger events via standard callbacks in widget testing. · matplotlib/matplotlib@aaa1e20 · GitHub
[go: up one dir, main page]

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)
0