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

Skip to content

Commit c8f152a

Browse files
committed
Add default ignore method and check it in callbacks.
* Attribute name "active" can be confused with parameter to `RadioButtons`, but `RadioButtons` doesn't save that parameter as an attribute, so there's no name clash. BUT this is still really confusing to users. Consider renaming `AxesWidget.active`. * * * This could have been implemented as a decorator, but some callbacks wouldn't be compatible. For example, `SpanSelector.release` should not be ignored if widget was deactivated during mouse press. * * * `SpanSelector` and `RectangleSelector` already had `ignore` methods, but they do not call it in `update_background`. I don't change the current behavior, although it seems desirable.
1 parent 21bca27 commit c8f152a

1 file changed

Lines changed: 50 additions & 15 deletions

File tree

lib/matplotlib/widgets.py

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"""
1111

1212
from __future__ import print_function
13+
import functools
1314
import numpy as np
1415

1516
from mlab import dist
@@ -78,6 +79,7 @@ def __init__(self, ax):
7879
self.ax = ax
7980
self.canvas = ax.figure.canvas
8081
self.cids = []
82+
self.active = True
8183

8284
def connect_event(self, event, callback):
8385
self.canvas.mpl_connect(event, callback)
@@ -87,6 +89,14 @@ def disconnect_events(self):
8789
for c in self.cids:
8890
self.canvas.mpl_disconnect(c)
8991

92+
def ignore(self, event):
93+
"""Return True if event should be ignored.
94+
95+
This method (or a version of it) should be called at the beginning
96+
of any event callback.
97+
"""
98+
return not self.active
99+
90100

91101
class Button(AxesWidget):
92102
"""
@@ -155,6 +165,8 @@ def __init__(self, ax, label, image=None,
155165
self._lastcolor = color
156166

157167
def _click(self, event):
168+
if self.ignore(event):
169+
return
158170
if event.inaxes != self.ax:
159171
return
160172
if not self.eventson:
@@ -163,6 +175,8 @@ def _click(self, event):
163175
event.canvas.grab_mouse(self.ax)
164176

165177
def _release(self, event):
178+
if self.ignore(event):
179+
return
166180
if event.canvas.mouse_grabber != self.ax:
167181
return
168182
event.canvas.release_mouse(self.ax)
@@ -174,6 +188,8 @@ def _release(self, event):
174188
func(event)
175189

176190
def _motion(self, event):
191+
if self.ignore(event):
192+
return
177193
if event.inaxes==self.ax:
178194
c = self.hovercolor
179195
else:
@@ -303,6 +319,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',
303319

304320
def _update(self, event):
305321
'update the slider position'
322+
if self.ignore(event):
323+
return
324+
306325
if event.button != 1:
307326
return
308327

@@ -461,6 +480,8 @@ def __init__(self, ax, labels, actives):
461480
self.observers = {}
462481

463482
def _clicked(self, event):
483+
if self.ignore(event):
484+
return
464485
if event.button !=1 : return
465486
if event.inaxes != self.ax: return
466487

@@ -572,6 +593,8 @@ def __init__(self, ax, labels, active=0, activecolor='blue'):
572593
self.observers = {}
573594

574595
def _clicked(self, event):
596+
if self.ignore(event):
597+
return
575598
if event.button !=1 : return
576599
if event.inaxes != self.ax: return
577600
xy = self.ax.transAxes.inverted().transform_point((event.x, event.y))
@@ -795,16 +818,19 @@ def __init__(self, ax, useblit=False, **lineprops):
795818
self.background = None
796819
self.needclear = False
797820

798-
799821
def clear(self, event):
800822
'clear the cursor'
823+
if self.ignore(event):
824+
return
801825
if self.useblit:
802826
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
803827
self.linev.set_visible(False)
804828
self.lineh.set_visible(False)
805829

806830
def onmove(self, event):
807831
'on mouse motion draw the cursor if visible'
832+
if self.ignore(event):
833+
return
808834
if event.inaxes != self.ax:
809835
self.linev.set_visible(False)
810836
self.lineh.set_visible(False)
@@ -1021,17 +1047,21 @@ def new_axes(self,ax):
10211047

10221048
def update_background(self, event):
10231049
'force an update of the background'
1050+
# If you add a call to `ignore` here, you'll want to check edge case:
1051+
# `release` can call a draw event even when `ignore` is True.
10241052
if self.useblit:
10251053
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
10261054

1027-
10281055
def ignore(self, event):
10291056
'return ``True`` if *event* should be ignored'
1030-
return event.inaxes!=self.ax or not self.visible or event.button !=1
1057+
widget_off = not self.visible or not self.active
1058+
non_event = event.inaxes!=self.ax or event.button !=1
1059+
return widget_off or non_event
10311060

10321061
def press(self, event):
10331062
'on button press event'
1034-
if self.ignore(event): return
1063+
if self.ignore(event):
1064+
return
10351065
self.buttonDown = True
10361066

10371067
self.rect.set_visible(self.visible)
@@ -1041,10 +1071,12 @@ def press(self, event):
10411071
self.pressv = event.ydata
10421072
return False
10431073

1044-
10451074
def release(self, event):
10461075
'on button release event'
1047-
if self.pressv is None or (self.ignore(event) and not self.buttonDown): return
1076+
if self.ignore(event) and not self.buttonDown:
1077+
return
1078+
if self.pressv is None:
1079+
return
10481080
self.buttonDown = False
10491081

10501082
self.rect.set_visible(False)
@@ -1079,7 +1111,8 @@ def update(self):
10791111

10801112
def onmove(self, event):
10811113
'on motion notify event'
1082-
if self.pressv is None or self.ignore(event): return
1114+
if self.pressv is None or self.ignore(event):
1115+
return
10831116
x, y = event.xdata, event.ydata
10841117
self.prev = x, y
10851118
if self.direction == 'horizontal':
@@ -1255,7 +1288,6 @@ def update_background(self, event):
12551288

12561289
def ignore(self, event):
12571290
'return ``True`` if *event* should be ignored'
1258-
# If RectangleSelector is not active :
12591291
if not self.active:
12601292
return True
12611293

@@ -1296,10 +1328,8 @@ def ignore(self, event):
12961328

12971329
def press(self, event):
12981330
'on button press event'
1299-
# Is the correct button pressed within the correct axes?
1300-
if self.ignore(event): return
1301-
1302-
1331+
if self.ignore(event):
1332+
return
13031333
# make the drawed box/line visible get the click-coordinates,
13041334
# button, ...
13051335
self.to_draw.set_visible(self.visible)
@@ -1309,7 +1339,8 @@ def press(self, event):
13091339

13101340
def release(self, event):
13111341
'on button release event'
1312-
if self.eventpress is None or self.ignore(event): return
1342+
if self.eventpress is None or self.ignore(event):
1343+
return
13131344
# make the box/line invisible again
13141345
self.to_draw.set_visible(False)
13151346
self.canvas.draw()
@@ -1360,10 +1391,10 @@ def update(self):
13601391
self.canvas.draw_idle()
13611392
return False
13621393

1363-
13641394
def onmove(self, event):
13651395
'on motion notify event if box/line is wanted'
1366-
if self.eventpress is None or self.ignore(event): return
1396+
if self.eventpress is None or self.ignore(event):
1397+
return
13671398
x,y = event.xdata, event.ydata # actual position (with
13681399
# (button still pressed)
13691400
if self.drawtype == 'box':
@@ -1411,6 +1442,8 @@ def __init__(self, ax, xy, callback=None, useblit=True):
14111442
self.connect_event('motion_notify_event', self.onmove)
14121443

14131444
def onrelease(self, event):
1445+
if self.ignore(event):
1446+
return
14141447
if self.verts is not None:
14151448
self.verts.append((event.xdata, event.ydata))
14161449
if len(self.verts)>2:
@@ -1420,6 +1453,8 @@ def onrelease(self, event):
14201453
self.disconnect_events()
14211454

14221455
def onmove(self, event):
1456+
if self.ignore(event):
1457+
return
14231458
if self.verts is None: return
14241459
if event.inaxes != self.ax: return
14251460
if event.button!=1: return

0 commit comments

Comments
 (0)