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

Skip to content

Commit c25efbd

Browse files
committed
Improve handling of out-of-bounds releases
1 parent f3261cf commit c25efbd

File tree

2 files changed

+38
-29
lines changed

2 files changed

+38
-29
lines changed

lib/matplotlib/tests/test_widgets.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ def onselect(epress, erelease):
7272
ax._got_onselect = True
7373
assert epress.xdata == 100
7474
assert epress.ydata == 100
75-
assert erelease.xdata == 150
76-
assert erelease.ydata == 150
75+
assert erelease.xdata == 200
76+
assert erelease.ydata == 200
7777

7878
tool = widgets.RectangleSelector(ax, onselect, **kwargs)
7979
event = get_event(ax, xdata=100, ydata=100, button=1)
@@ -82,7 +82,8 @@ def onselect(epress, erelease):
8282
event = get_event(ax, xdata=125, ydata=125, button=1)
8383
tool.onmove(event)
8484

85-
event = get_event(ax, xdata=150, ydata=150, button=1)
85+
# purposely drag outside of axis for release
86+
event = get_event(ax, xdata=250, ydata=250, button=1)
8687
tool.release(event)
8788

8889
assert ax._got_onselect

lib/matplotlib/widgets.py

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from __future__ import (absolute_import, division, print_function,
1313
unicode_literals)
1414

15+
import copy
1516
import six
1617
from six.moves import zip
1718

@@ -1163,19 +1164,8 @@ def ignore(self, event):
11631164
return event.inaxes != self.ax
11641165

11651166
# If a button was pressed, check if the release-button is the
1166-
# same. If event is out of axis, limit the data coordinates to axes
1167-
# boundaries.
1168-
if event.button == self.eventpress.button and event.inaxes != self.ax:
1169-
(xdata, ydata) = self.ax.transData.inverted().transform_point(
1170-
(event.x, event.y))
1171-
x0, x1 = self.ax.get_xbound()
1172-
y0, y1 = self.ax.get_ybound()
1173-
xdata = max(x0, xdata)
1174-
xdata = min(x1, xdata)
1175-
ydata = max(y0, ydata)
1176-
ydata = min(y1, ydata)
1177-
event.xdata = xdata
1178-
event.ydata = ydata
1167+
# same.
1168+
if event.button == self.eventpress.button:
11791169
return False
11801170

11811171
# If a button was pressed, check if the release-button is the
@@ -1206,17 +1196,31 @@ def update(self):
12061196
self.canvas.draw_idle()
12071197
return False
12081198

1199+
def _get_data(self, event):
1200+
"""Limit the xdata and ydata to the axes limits"""
1201+
x0, x1 = self.ax.get_xbound()
1202+
y0, y1 = self.ax.get_ybound()
1203+
xdata = max(x0, event.xdata)
1204+
xdata = min(x1, xdata)
1205+
ydata = max(y0, event.ydata)
1206+
ydata = min(y1, ydata)
1207+
return xdata, ydata
1208+
12091209
def press(self, event):
12101210
"""Button press handler"""
12111211
if not self.ignore(event):
1212-
self.eventpress = event
1212+
self.eventpress = copy.copy(event)
1213+
self.eventpress.xdata, self.eventpress.ydata = (
1214+
self._get_data(event))
12131215
return True
12141216
return False
12151217

12161218
def release(self, event):
12171219
"""Button release event"""
12181220
if not self.ignore(event) and not self.eventpress is None:
1219-
self.eventrelease = event
1221+
self.eventrelease = copy.copy(event)
1222+
self.eventrelease.xdata, self.eventrelease.ydata = (
1223+
self._get_data(event))
12201224
return True
12211225
else:
12221226
return False
@@ -1363,10 +1367,11 @@ def press(self, event):
13631367
if self.span_stays:
13641368
self.stay_rect.set_visible(False)
13651369

1370+
xdata, ydata = self._get_data(event)
13661371
if self.direction == 'horizontal':
1367-
self.pressv = event.xdata
1372+
self.pressv = xdata
13681373
else:
1369-
self.pressv = event.ydata
1374+
self.pressv = ydata
13701375
return False
13711376

13721377
def release(self, event):
@@ -1386,10 +1391,11 @@ def release(self, event):
13861391

13871392
self.canvas.draw()
13881393
vmin = self.pressv
1394+
xdata, ydata = self._get_data(event)
13891395
if self.direction == 'horizontal':
1390-
vmax = event.xdata or self.prev[0]
1396+
vmax = xdata or self.prev[0]
13911397
else:
1392-
vmax = event.ydata or self.prev[1]
1398+
vmax = ydata or self.prev[1]
13931399

13941400
if vmin > vmax:
13951401
vmin, vmax = vmax, vmin
@@ -1404,7 +1410,7 @@ def onmove(self, event):
14041410
"""on motion notify event"""
14051411
if self.pressv is None or self.ignore(event):
14061412
return
1407-
x, y = event.xdata, event.ydata
1413+
x, y = self._get_data(event)
14081414
self.prev = x, y
14091415
if self.direction == 'horizontal':
14101416
v = x
@@ -1423,10 +1429,11 @@ def onmove(self, event):
14231429

14241430
if self.onmove_callback is not None:
14251431
vmin = self.pressv
1432+
xdata, ydata = self._get_data(event)
14261433
if self.direction == 'horizontal':
1427-
vmax = event.xdata or self.prev[0]
1434+
vmax = xdata or self.prev[0]
14281435
else:
1429-
vmax = event.ydata or self.prev[1]
1436+
vmax = ydata or self.prev[1]
14301437

14311438
if vmin > vmax:
14321439
vmin, vmax = vmax, vmin
@@ -1609,7 +1616,8 @@ def onmove(self, event):
16091616
"""on motion notify event if box/line is wanted"""
16101617
if self.eventpress is None or self.ignore(event):
16111618
return
1612-
x, y = event.xdata, event.ydata # actual position (with
1619+
1620+
x, y = self._get_data(event) # actual position (with
16131621
# (button still pressed)
16141622
if self.drawtype == 'box':
16151623
minx, maxx = self.eventpress.xdata, x # click-x and actual mouse-x
@@ -1695,7 +1703,7 @@ def onpress(self, event):
16951703
def press(self, event):
16961704
if not _SelectorWidget.press(self, event):
16971705
return
1698-
self.verts = [(event.xdata, event.ydata)]
1706+
self.verts = [self._get_data(event)]
16991707
self.line.set_visible(True)
17001708

17011709
def onrelease(self, event):
@@ -1705,7 +1713,7 @@ def release(self, event):
17051713
if not _SelectorWidget.release(self, event):
17061714
return
17071715
if self.verts is not None:
1708-
self.verts.append((event.xdata, event.ydata))
1716+
self.verts.append(self._get_data(event))
17091717
self.onselect(self.verts)
17101718
self.line.set_data([[], []])
17111719
self.line.set_visible(False)
@@ -1714,7 +1722,7 @@ def release(self, event):
17141722
def onmove(self, event):
17151723
if self.ignore(event) or self.verts is None:
17161724
return
1717-
self.verts.append((event.xdata, event.ydata))
1725+
self.verts.append(self._get_data(event))
17181726

17191727
self.line.set_data(list(zip(*self.verts)))
17201728

0 commit comments

Comments
 (0)