Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4013172

Browse files
authored
Merge pull request #20113 from ericpre/interactive_span_selector
Interactive span selector improvement
2 parents 108e1b0 + 92d1705 commit 4013172

File tree

5 files changed

+528
-165
lines changed

5 files changed

+528
-165
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
SpanSelector
2+
~~~~~~~~~~~~
3+
``span_stays`` is deprecated, use ``interactive`` argument instead
4+
Several `~matplotlib.widgets.SpanSelector` class internals have been privatized
5+
and deprecated:
6+
- ``pressv``
7+
- ``prev``
8+
- ``rect``
9+
- ``rectprops``
10+
- ``active_handle``
11+
- ``span_stays``
12+
13+
14+
Several `~matplotlib.widgets.RectangleSelector` and
15+
`~matplotlib.widgets.EllipseSelector` class internals have been privatized and
16+
deprecated:
17+
- ``to_draw``
18+
- ``drawtype``
19+
- ``rectprops``
20+
- ``active_handle``
21+
- ``interactive``
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
Dragging selectors
22
------------------
33

4-
The `~matplotlib.widgets.RectangleSelector` and
5-
`~matplotlib.widgets.EllipseSelector` have a new keyword argument,
4+
The `~matplotlib.widgets.SpanSelector`, `~matplotlib.widgets.RectangleSelector`
5+
and `~matplotlib.widgets.EllipseSelector` have a new keyword argument,
66
*drag_from_anywhere*, which when set to `True` allows you to click and drag
77
from anywhere inside the selector to move it. Previously it was only possible
88
to move it by either activating the move modifier button, or clicking on the
99
central handle.
10+
11+
The size of the `~matplotlib.widgets.SpanSelector` can now be changed using
12+
the edge handles.

examples/widgets/span_selector.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
fig, (ax1, ax2) = plt.subplots(2, figsize=(8, 6))
1717

1818
x = np.arange(0.0, 5.0, 0.01)
19-
y = np.sin(2*np.pi*x) + 0.5*np.random.randn(len(x))
19+
y = np.sin(2 * np.pi * x) + 0.5 * np.random.randn(len(x))
2020

2121
ax1.plot(x, y)
2222
ax1.set_ylim(-2, 2)
@@ -37,7 +37,8 @@ def onselect(xmin, xmax):
3737
line2.set_data(region_x, region_y)
3838
ax2.set_xlim(region_x[0], region_x[-1])
3939
ax2.set_ylim(region_y.min(), region_y.max())
40-
fig.canvas.draw()
40+
fig.canvas.draw_idle()
41+
4142

4243
#############################################################################
4344
# .. note::
@@ -47,8 +48,15 @@ def onselect(xmin, xmax):
4748
#
4849

4950

50-
span = SpanSelector(ax1, onselect, 'horizontal', useblit=True,
51-
rectprops=dict(alpha=0.5, facecolor='tab:blue'))
51+
span = SpanSelector(
52+
ax1,
53+
onselect,
54+
"horizontal",
55+
useblit=True,
56+
rectprops=dict(alpha=0.5, facecolor="tab:blue"),
57+
interactive=True,
58+
drag_from_anywhere=True
59+
)
5260
# Set useblit=True on most backends for enhanced performance.
5361

5462

lib/matplotlib/tests/test_widgets.py

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,21 @@ def check_span(*args, **kwargs):
195195
def onselect(vmin, vmax):
196196
ax._got_onselect = True
197197
assert vmin == 100
198-
assert vmax == 150
198+
assert vmax == 199
199199

200200
def onmove(vmin, vmax):
201201
assert vmin == 100
202-
assert vmax == 125
202+
assert vmax == 199
203203
ax._got_on_move = True
204204

205205
if 'onmove_callback' in kwargs:
206206
kwargs['onmove_callback'] = onmove
207207

208208
tool = widgets.SpanSelector(ax, onselect, *args, **kwargs)
209209
do_event(tool, 'press', xdata=100, ydata=100, button=1)
210-
do_event(tool, 'onmove', xdata=125, ydata=125, button=1)
211-
do_event(tool, 'release', xdata=150, ydata=150, button=1)
210+
# move outside of axis
211+
do_event(tool, 'onmove', xdata=199, ydata=199, button=1)
212+
do_event(tool, 'release', xdata=250, ydata=250, button=1)
212213

213214
assert ax._got_onselect
214215

@@ -222,6 +223,85 @@ def test_span_selector():
222223
check_span('horizontal', rectprops=dict(fill=True))
223224

224225

226+
@pytest.mark.parametrize('drag_from_anywhere', [True, False])
227+
def test_span_selector_drag(drag_from_anywhere):
228+
ax = get_ax()
229+
230+
def onselect(epress, erelease):
231+
pass
232+
233+
# Create span
234+
tool = widgets.SpanSelector(ax, onselect, 'horizontal', interactive=True,
235+
drag_from_anywhere=drag_from_anywhere)
236+
do_event(tool, 'press', xdata=10, ydata=10, button=1)
237+
do_event(tool, 'onmove', xdata=100, ydata=120, button=1)
238+
do_event(tool, 'release', xdata=100, ydata=120, button=1)
239+
assert tool.extents == (10, 100)
240+
# Drag inside span
241+
#
242+
# If drag_from_anywhere == True, this will move the span by 10,
243+
# giving new value extents = 20, 110
244+
#
245+
# If drag_from_anywhere == False, this will create a new span with
246+
# value extents = 25, 35
247+
do_event(tool, 'press', xdata=25, ydata=15, button=1)
248+
do_event(tool, 'onmove', xdata=35, ydata=25, button=1)
249+
do_event(tool, 'release', xdata=35, ydata=25, button=1)
250+
if drag_from_anywhere:
251+
assert tool.extents == (20, 110)
252+
else:
253+
assert tool.extents == (25, 35)
254+
255+
# Check that in both cases, dragging outside the span draws a new span
256+
do_event(tool, 'press', xdata=175, ydata=185, button=1)
257+
do_event(tool, 'onmove', xdata=185, ydata=195, button=1)
258+
do_event(tool, 'release', xdata=185, ydata=195, button=1)
259+
assert tool.extents == (175, 185)
260+
261+
262+
def test_span_selector_direction():
263+
ax = get_ax()
264+
265+
def onselect(epress, erelease):
266+
pass
267+
268+
tool = widgets.SpanSelector(ax, onselect, 'horizontal', interactive=True)
269+
assert tool.direction == 'horizontal'
270+
assert tool._edge_handles.direction == 'horizontal'
271+
272+
with pytest.raises(ValueError):
273+
tool = widgets.SpanSelector(ax, onselect, 'invalid_direction')
274+
275+
tool.direction = 'vertical'
276+
assert tool.direction == 'vertical'
277+
assert tool._edge_handles.direction == 'vertical'
278+
279+
with pytest.raises(ValueError):
280+
tool.direction = 'invalid_string'
281+
282+
283+
def test_tool_line_handle():
284+
ax = get_ax()
285+
286+
positions = [20, 30, 50]
287+
288+
tool_line_handle = widgets.ToolLineHandles(ax, positions, 'horizontal',
289+
useblit=False)
290+
291+
for artist in tool_line_handle.artists:
292+
assert not artist.get_animated()
293+
assert not artist.get_visible()
294+
295+
tool_line_handle.set_visible(True)
296+
tool_line_handle.set_animated(True)
297+
298+
for artist in tool_line_handle.artists:
299+
assert artist.get_animated()
300+
assert artist.get_visible()
301+
302+
assert tool_line_handle.positions == positions
303+
304+
225305
def check_lasso_selector(**kwargs):
226306
ax = get_ax()
227307

0 commit comments

Comments
 (0)