Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbbf32b8

Browse files
committed
Allow Selectors to be dragged from anywhere within their patch
1 parent906cae4 commitbbf32b8

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Dragging selectors
2+
------------------
3+
4+
The `~matplotlib.widgets.RectangleSelector` and
5+
`~matplotlib.widgets.EllipseSelector` have a new keyword argument,
6+
``drag_from_anywhere``, which when set to `True` allows you to click and drag
7+
from anywhere inside the selector to move it. Previously it was only possible
8+
to move it by either activating the move modifier button, or clicking on the
9+
central handle.

‎lib/matplotlib/tests/test_widgets.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,36 @@ def test_rectangle_selector():
4444
check_rectangle(rectprops=dict(fill=True))
4545

4646

47+
@pytest.mark.parametrize('drag_from_anywhere, new_center',
48+
[[True, (100,100)],
49+
[False, (50,50)]])
50+
deftest_rectangle_drag(drag_from_anywhere,new_center):
51+
ax=get_ax()
52+
53+
defonselect(epress,erelease):
54+
pass
55+
56+
tool=widgets.RectangleSelector(ax,onselect,interactive=True,
57+
drag_from_anywhere=drag_from_anywhere)
58+
# Create rectangle
59+
do_event(tool,'press',xdata=0,ydata=0,button=1)
60+
do_event(tool,'onmove',xdata=100,ydata=100,button=1)
61+
do_event(tool,'release',xdata=100,ydata=100,button=1)
62+
asserttool.center== (50,50)
63+
# Drag inside rectangle, but away from centre handle to make sure rectangle
64+
# is still moved
65+
do_event(tool,'press',xdata=25,ydata=25,button=1)
66+
do_event(tool,'onmove',xdata=75,ydata=75,button=1)
67+
do_event(tool,'release',xdata=75,ydata=75,button=1)
68+
asserttool.center==new_center
69+
# Check that in both cases, dragging outside the rectangle draws a new
70+
# rectangle
71+
do_event(tool,'press',xdata=175,ydata=175,button=1)
72+
do_event(tool,'onmove',xdata=185,ydata=185,button=1)
73+
do_event(tool,'release',xdata=185,ydata=185,button=1)
74+
asserttool.center== (180,180)
75+
76+
4777
deftest_ellipse():
4878
"""For ellipse, test out the key modifiers"""
4979
ax=get_ax()

‎lib/matplotlib/widgets.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,8 @@ def __init__(self, ax, onselect, drawtype='box',
21892189
minspanx=0,minspany=0,useblit=False,
21902190
lineprops=None,rectprops=None,spancoords='data',
21912191
button=None,maxdist=10,marker_props=None,
2192-
interactive=False,state_modifier_keys=None):
2192+
interactive=False,state_modifier_keys=None,
2193+
drag_from_anywhere=False):
21932194
r"""
21942195
Parameters
21952196
----------
@@ -2261,13 +2262,18 @@ def onselect(eclick: MouseEvent, erelease: MouseEvent)
22612262
default: "ctrl".
22622263
22632264
"square" and "center" can be combined.
2265+
2266+
drag_from_anywhere : bool, optional
2267+
If `True`, the widget can be moved by clicking anywhere within
2268+
its bounds.
22642269
"""
22652270
super().__init__(ax,onselect,useblit=useblit,button=button,
22662271
state_modifier_keys=state_modifier_keys)
22672272

22682273
self.to_draw=None
22692274
self.visible=True
22702275
self.interactive=interactive
2276+
self.drag_from_anywhere=drag_from_anywhere
22712277

22722278
ifdrawtype=='none':# draw a line but make it invisible
22732279
drawtype='line'
@@ -2407,8 +2413,9 @@ def _onmove(self, event):
24072413
y1=event.ydata
24082414

24092415
# move existing shape
2410-
elif (('move'inself.stateorself.active_handle=='C')
2411-
andself._extents_on_pressisnotNone):
2416+
elif (('move'inself.stateorself.active_handle=='C'or
2417+
(self.drag_from_anywhereandself._contains(event)))and
2418+
self._extents_on_pressisnotNone):
24122419
x0,x1,y0,y1=self._extents_on_press
24132420
dx=event.xdata-self.eventpress.xdata
24142421
dy=event.ydata-self.eventpress.ydata
@@ -2536,19 +2543,28 @@ def _set_active_handle(self, event):
25362543
e_idx,e_dist=self._edge_handles.closest(event.x,event.y)
25372544
m_idx,m_dist=self._center_handle.closest(event.x,event.y)
25382545

2546+
contains=self._contains(event)
25392547
if'move'inself.state:
25402548
self.active_handle='C'
25412549
self._extents_on_press=self.extents
2542-
25432550
# Set active handle as closest handle, if mouse click is close enough.
25442551
elifm_dist<self.maxdist*2:
2552+
# Prioritise center handle over other handles
25452553
self.active_handle='C'
2546-
elifc_dist>self.maxdistande_dist>self.maxdist:
2547-
self.active_handle=None
2548-
return
2554+
elif (c_dist>self.maxdistande_dist>self.maxdist):
2555+
# Not close to any handles
2556+
ifself.drag_from_anywhereandcontains:
2557+
# Check if we've clicked inside the region
2558+
self.active_handle='C'
2559+
self._extents_on_press=self.extents
2560+
else:
2561+
self.active_handle=None
2562+
return
25492563
elifc_dist<e_dist:
2564+
# Closest to a corner handle
25502565
self.active_handle=self._corner_order[c_idx]
25512566
else:
2567+
# Closest to an edge handle
25522568
self.active_handle=self._edge_order[e_idx]
25532569

25542570
# Save coordinates of rectangle at the start of handle movement.
@@ -2560,6 +2576,10 @@ def _set_active_handle(self, event):
25602576
y0,y1=y1,event.ydata
25612577
self._extents_on_press=x0,x1,y0,y1
25622578

2579+
def_contains(self,event):
2580+
"""Return True if event is within the patch."""
2581+
returnself.to_draw.contains(event,radius=0)[0]
2582+
25632583
@property
25642584
defgeometry(self):
25652585
"""

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp