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

Skip to content

Commit 97d023d

Browse files
committed
Merge pull request #552 from dhyams/double_click
Double click support for matplotlib
2 parents 2c6c369 + b1e40e8 commit 97d023d

10 files changed

Lines changed: 127 additions & 15 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env python
2+
import matplotlib
3+
#matplotlib.use("WxAgg")
4+
#matplotlib.use("TkAgg")
5+
#matplotlib.use("GTKAgg")
6+
#matplotlib.use("QtAgg")
7+
#matplotlib.use("Qt4Agg")
8+
#matplotlib.use("CocoaAgg")
9+
#matplotlib.use("MacOSX")
10+
import matplotlib.pyplot as plt
11+
12+
#print "***** TESTING WITH BACKEND: %s"%matplotlib.get_backend() + " *****"
13+
14+
def OnClick(event):
15+
if event.dblclick:
16+
print "DBLCLICK",event
17+
else:
18+
print "DOWN ",event
19+
20+
def OnRelease(event):
21+
print "UP ",event
22+
23+
24+
fig = plt.gcf()
25+
cid_up = fig.canvas.mpl_connect('button_press_event',OnClick)
26+
cid_down = fig.canvas.mpl_connect('button_release_event',OnRelease)
27+
28+
plt.gca().text(0.5,0.5,"Click on the canvas to test mouse events.",ha="center",va="center")
29+
30+
plt.show()
31+

lib/matplotlib/backend_bases.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,13 +1304,14 @@ def on_press(event):
13041304
x = None # x position - pixels from left of canvas
13051305
y = None # y position - pixels from right of canvas
13061306
button = None # button pressed None, 1, 2, 3
1307+
dblclick = None # whether or not the event is the result of a double click
13071308
inaxes = None # the Axes instance if mouse us over axes
13081309
xdata = None # x coord of mouse in data coords
13091310
ydata = None # y coord of mouse in data coords
13101311
step = None # scroll steps for scroll events
13111312

13121313
def __init__(self, name, canvas, x, y, button=None, key=None,
1313-
step=0, guiEvent=None):
1314+
step=0, dblclick=False, guiEvent=None):
13141315
"""
13151316
x, y in figure coords, 0,0 = bottom, left
13161317
button pressed None, 1, 2, 3, 'up', 'down'
@@ -1319,6 +1320,11 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
13191320
self.button = button
13201321
self.key = key
13211322
self.step = step
1323+
self.dblclick = dblclick
1324+
1325+
def __str__(self):
1326+
return "MPL MouseEvent: xy=(%d,%d) xydata=(%s,%s) button=%d dblclick=%s inaxes=%s"%\
1327+
(self.x,self.y,str(self.xdata),str(self.ydata),self.button,self.dblclick,self.inaxes)
13221328

13231329
class PickEvent(Event):
13241330
"""
@@ -1616,7 +1622,7 @@ def scroll_event(self, x, y, step, guiEvent=None):
16161622
self.callbacks.process(s, mouseevent)
16171623

16181624

1619-
def button_press_event(self, x, y, button, guiEvent=None):
1625+
def button_press_event(self, x, y, button, dblclick=False, guiEvent=None):
16201626
"""
16211627
Backend derived classes should call this function on any mouse
16221628
button press. x,y are the canvas coords: 0,0 is lower, left.
@@ -1628,7 +1634,7 @@ def button_press_event(self, x, y, button, guiEvent=None):
16281634
"""
16291635
self._button = button
16301636
s = 'button_press_event'
1631-
mouseevent = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent)
1637+
mouseevent = MouseEvent(s, self, x, y, button, self._key, dblclick=dblclick, guiEvent=guiEvent)
16321638
self.callbacks.process(s, mouseevent)
16331639

16341640
def button_release_event(self, x, y, button, guiEvent=None):

lib/matplotlib/backends/backend_cocoaagg.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,15 @@ def windowDidResize_(self, sender):
166166
self.updatePlot()
167167

168168
def mouseDown_(self, event):
169+
dblclick = (event.clickCount() == 2)
169170
loc = self.convertPoint_fromView_(event.locationInWindow(), None)
170171
type = event.type()
171172
if (type == NSLeftMouseDown):
172173
button = 1
173174
else:
174175
print >>sys.stderr, 'Unknown mouse event type:', type
175176
button = -1
176-
self.canvas.button_press_event(loc.x, loc.y, button)
177+
self.canvas.button_press_event(loc.x, loc.y, button, dblclick=dblclick)
177178
self.updatePlot()
178179

179180
def mouseDragged_(self, event):

lib/matplotlib/backends/backend_fltkagg.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ def handle(self, event):
155155
if self._draw_overlay:
156156
self._oldx=x
157157
self._oldy=y
158-
if Fltk.Fl.event_clicks():
159-
FigureCanvasBase.button_press_event(self._source, x, yf, self._button)
158+
if Fltk.Fl.event_clicks(): # according to docs, event_clicks() returns nonzero if this is a double click.
159+
FigureCanvasBase.button_press_event(self._source, x, yf, self._button, dblclick=True)
160160
return 1
161161
else:
162162
FigureCanvasBase.button_press_event(self._source, x, yf, self._button)

lib/matplotlib/backends/backend_gtk.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ def __init__(self, figure):
224224

225225
self._idle_event_id = gobject.idle_add(self.idle_event)
226226

227+
self.last_downclick = {}
228+
227229
def destroy(self):
228230
#gtk.DrawingArea.destroy(self)
229231
self.close_event()
@@ -248,7 +250,23 @@ def button_press_event(self, widget, event):
248250
x = event.x
249251
# flipy so y=0 is bottom of canvas
250252
y = self.allocation.height - event.y
251-
FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event)
253+
dblclick = (event.type == gdk._2BUTTON_PRESS)
254+
if not dblclick:
255+
# GTK is the only backend that generates a DOWN-UP-DOWN-DBLCLICK-UP event
256+
# sequence for a double click. All other backends have a DOWN-UP-DBLCLICK-UP
257+
# sequence. In order to provide consistency to matplotlib users, we will
258+
# eat the extra DOWN event in the case that we detect it is part of a double
259+
# click.
260+
# first, get the double click time in milliseconds.
261+
current_time = event.get_time()
262+
last_time = self.last_downclick.get(event.button,0)
263+
dblclick_time = gtk.settings_get_for_screen(gdk.screen_get_default()).get_property('gtk-double-click-time')
264+
delta_time = current_time-last_time
265+
if delta_time < dblclick_time:
266+
del self.last_downclick[event.button] # we do not want to eat more than one event.
267+
return False # eat.
268+
self.last_downclick[event.button] = current_time
269+
FigureCanvasBase.button_press_event(self, x, y, event.button, dblclick=dblclick, guiEvent=event)
252270
return False # finish event propagation?
253271

254272
def button_release_event(self, widget, event):

lib/matplotlib/backends/backend_qt.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ def mousePressEvent( self, event ):
108108
FigureCanvasBase.button_press_event( self, x, y, button )
109109
if DEBUG: print 'button pressed:', event.button()
110110

111+
def mouseDoubleClickEvent( self, event ):
112+
x = event.pos().x()
113+
# flipy so y=0 is bottom of canvas
114+
y = self.figure.bbox.height - event.pos().y()
115+
button = self.buttond[event.button()]
116+
FigureCanvasBase.button_press_event( self, x, y, button, dblclick=True )
117+
if DEBUG: print 'button doubleclicked:', event.button()
118+
111119
def mouseMoveEvent( self, event ):
112120
x = event.x()
113121
# flipy so y=0 is bottom of canvas

lib/matplotlib/backends/backend_qt4.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ def mousePressEvent( self, event ):
181181
FigureCanvasBase.button_press_event( self, x, y, button )
182182
if DEBUG: print 'button pressed:', event.button()
183183

184+
def mouseDoubleClickEvent(self, event):
185+
x = event.pos().x()
186+
# flipy so y=0 is bottom of canvas
187+
y = self.figure.bbox.height - event.pos().y()
188+
button = self.buttond[event.button()]
189+
FigureCanvasBase.button_press_event( self, x, y, button, dblclick=True )
190+
if DEBUG: print 'button doubleclicked:', event.button()
191+
184192
def mouseMoveEvent( self, event ):
185193
x = event.x()
186194
# flipy so y=0 is bottom of canvas

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ def __init__(self, figure, master=None, resize_callback=None):
193193
self._tkcanvas.bind("<KeyRelease>", self.key_release)
194194
for name in "<Button-1>", "<Button-2>", "<Button-3>":
195195
self._tkcanvas.bind(name, self.button_press_event)
196+
for name in "<Double-Button-1>", "<Double-Button-2>", "<Double-Button-3>":
197+
self._tkcanvas.bind(name, self.button_dblclick_event)
196198
for name in "<ButtonRelease-1>", "<ButtonRelease-2>", "<ButtonRelease-3>":
197199
self._tkcanvas.bind(name, self.button_release_event)
198200

@@ -271,7 +273,7 @@ def motion_notify_event(self, event):
271273
FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event)
272274

273275

274-
def button_press_event(self, event):
276+
def button_press_event(self, event, dblclick=False):
275277
x = event.x
276278
# flipy so y=0 is bottom of canvas
277279
y = self.figure.bbox.height - event.y
@@ -283,7 +285,10 @@ def button_press_event(self, event):
283285
if num==2: num=3
284286
elif num==3: num=2
285287

286-
FigureCanvasBase.button_press_event(self, x, y, num, guiEvent=event)
288+
FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, guiEvent=event)
289+
290+
def button_dblclick_event(self,event):
291+
self.button_press_event(event,dblclick=True)
287292

288293
def button_release_event(self, event):
289294
x = event.x

lib/matplotlib/backends/backend_wx.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -739,19 +739,19 @@ def do_nothing(*args, **kwargs):
739739
bind(self, wx.EVT_KEY_DOWN, self._onKeyDown)
740740
bind(self, wx.EVT_KEY_UP, self._onKeyUp)
741741
bind(self, wx.EVT_RIGHT_DOWN, self._onRightButtonDown)
742-
bind(self, wx.EVT_RIGHT_DCLICK, self._onRightButtonDown)
742+
bind(self, wx.EVT_RIGHT_DCLICK, self._onRightButtonDClick)
743743
bind(self, wx.EVT_RIGHT_UP, self._onRightButtonUp)
744744
bind(self, wx.EVT_MOUSEWHEEL, self._onMouseWheel)
745745
bind(self, wx.EVT_LEFT_DOWN, self._onLeftButtonDown)
746-
bind(self, wx.EVT_LEFT_DCLICK, self._onLeftButtonDown)
746+
bind(self, wx.EVT_LEFT_DCLICK, self._onLeftButtonDClick)
747747
bind(self, wx.EVT_LEFT_UP, self._onLeftButtonUp)
748748
bind(self, wx.EVT_MOTION, self._onMotion)
749749
bind(self, wx.EVT_LEAVE_WINDOW, self._onLeave)
750750
bind(self, wx.EVT_ENTER_WINDOW, self._onEnter)
751751
bind(self, wx.EVT_IDLE, self._onIdle)
752752
#Add middle button events
753753
bind(self, wx.EVT_MIDDLE_DOWN, self._onMiddleButtonDown)
754-
bind(self, wx.EVT_MIDDLE_DCLICK, self._onMiddleButtonDown)
754+
bind(self, wx.EVT_MIDDLE_DCLICK, self._onMiddleButtonDClick)
755755
bind(self, wx.EVT_MIDDLE_UP, self._onMiddleButtonUp)
756756

757757
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
@@ -1271,6 +1271,13 @@ def _onRightButtonDown(self, evt):
12711271
self.CaptureMouse()
12721272
FigureCanvasBase.button_press_event(self, x, y, 3, guiEvent=evt)
12731273

1274+
def _onRightButtonDClick(self, evt):
1275+
"""Start measuring on an axis."""
1276+
x = evt.GetX()
1277+
y = self.figure.bbox.height - evt.GetY()
1278+
evt.Skip()
1279+
self.CaptureMouse()
1280+
FigureCanvasBase.button_press_event(self, x, y, 3, dblclick=True,guiEvent=evt)
12741281

12751282
def _onRightButtonUp(self, evt):
12761283
"""End measuring on an axis."""
@@ -1288,6 +1295,14 @@ def _onLeftButtonDown(self, evt):
12881295
self.CaptureMouse()
12891296
FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt)
12901297

1298+
def _onLeftButtonDClick(self, evt):
1299+
"""Start measuring on an axis."""
1300+
x = evt.GetX()
1301+
y = self.figure.bbox.height - evt.GetY()
1302+
evt.Skip()
1303+
self.CaptureMouse()
1304+
FigureCanvasBase.button_press_event(self, x, y, 1, dblclick=True, guiEvent=evt)
1305+
12911306
def _onLeftButtonUp(self, evt):
12921307
"""End measuring on an axis."""
12931308
x = evt.GetX()
@@ -1306,6 +1321,14 @@ def _onMiddleButtonDown(self, evt):
13061321
self.CaptureMouse()
13071322
FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt)
13081323

1324+
def _onMiddleButtonDClick(self, evt):
1325+
"""Start measuring on an axis."""
1326+
x = evt.GetX()
1327+
y = self.figure.bbox.height - evt.GetY()
1328+
evt.Skip()
1329+
self.CaptureMouse()
1330+
FigureCanvasBase.button_press_event(self, x, y, 2, dblclick=True, guiEvent=evt)
1331+
13091332
def _onMiddleButtonUp(self, evt):
13101333
"""End measuring on an axis."""
13111334
x = evt.GetX()

src/_macosx.m

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5100,6 +5100,7 @@ - (void)mouseDown:(NSEvent *)event
51005100
{
51015101
int x, y;
51025102
int num;
5103+
int dblclick = 0;
51035104
PyObject* result;
51045105
PyGILState_STATE gstate;
51055106
NSPoint location = [event locationInWindow];
@@ -5127,8 +5128,11 @@ - (void)mouseDown:(NSEvent *)event
51275128
case NSRightMouseDown: num = 3; break;
51285129
default: return; /* Unknown mouse event */
51295130
}
5131+
if ([event clickCount] == 2) {
5132+
dblclick = 1;
5133+
}
51305134
gstate = PyGILState_Ensure();
5131-
result = PyObject_CallMethod(canvas, "button_press_event", "iii", x, y, num);
5135+
result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick);
51325136
if(result)
51335137
Py_DECREF(result);
51345138
else
@@ -5205,14 +5209,18 @@ - (void)rightMouseDown:(NSEvent *)event
52055209
{
52065210
int x, y;
52075211
int num = 3;
5212+
int dblclick = 0;
52085213
PyObject* result;
52095214
PyGILState_STATE gstate;
52105215
NSPoint location = [event locationInWindow];
52115216
location = [self convertPoint: location fromView: nil];
52125217
x = location.x;
52135218
y = location.y;
52145219
gstate = PyGILState_Ensure();
5215-
result = PyObject_CallMethod(canvas, "button_press_event", "iii", x, y, num);
5220+
if ([event clickCount] == 2) {
5221+
dblclick = 1;
5222+
}
5223+
result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick);
52165224
if(result)
52175225
Py_DECREF(result);
52185226
else
@@ -5262,14 +5270,18 @@ - (void)otherMouseDown:(NSEvent *)event
52625270
{
52635271
int x, y;
52645272
int num = 2;
5273+
int dblclick = 0;
52655274
PyObject* result;
52665275
PyGILState_STATE gstate;
52675276
NSPoint location = [event locationInWindow];
52685277
location = [self convertPoint: location fromView: nil];
52695278
x = location.x;
52705279
y = location.y;
52715280
gstate = PyGILState_Ensure();
5272-
result = PyObject_CallMethod(canvas, "button_press_event", "iii", x, y, num);
5281+
if ([event clickCount] == 2) {
5282+
dblclick = 1;
5283+
}
5284+
result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick);
52735285
if(result)
52745286
Py_DECREF(result);
52755287
else

0 commit comments

Comments
 (0)