GitHub Viewer
diff --git a/doc/users/navigation_toolbar.rst b/doc/users/navigation_toolbar.rst
index 66848eab4e36..6e327621ba4b 100644
--- a/doc/users/navigation_toolbar.rst
+++ b/doc/users/navigation_toolbar.rst
@@ -83,23 +83,24 @@ Navigation Keyboard Shortcuts
The following table holds all the default keys, which can be overwritten by use of your matplotlibrc (#keymap.\*).
-================================== ==============================================
+================================== =================================================
Command Keyboard Shortcut(s)
-================================== ==============================================
+================================== =================================================
Home/Reset **h** or **r** or **home**
Back **c** or **left arrow** or **backspace**
Forward **v** or **right arrow**
Pan/Zoom **p**
Zoom-to-rect **o**
-Save **s**
-Toggle fullscreen **f**
-Constrain pan/zoom to x axis hold **x**
-Constrain pan/zoom to y axis hold **y**
-Preserve aspect ratio hold **CONTROL**
-Toggle grid **g**
-Toggle x axis scale (log/linear) **L** or **k**
-Toggle y axis scale (log/linear) **l**
-================================== ==============================================
+Save **ctrl** + **s**
+Toggle fullscreen **ctrl** + **f**
+Close plot **ctrl** + **w**
+Constrain pan/zoom to x axis hold **x** when panning/zooming with mouse
+Constrain pan/zoom to y axis hold **y** when panning/zooming with mouse
+Preserve aspect ratio hold **CONTROL** when panning/zooming with mouse
+Toggle grid **g** when mouse is over an axes
+Toggle x axis scale (log/linear) **L** or **k** when mouse is over an axes
+Toggle y axis scale (log/linear) **l** when mouse is over an axes
+================================== =================================================
If you are using :mod:`matplotlib.pyplot` the toolbar will be created
automatically for every figure. If you are writing your own user
diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py
index 7dc841db4aa4..b4f72651343a 100644
--- a/lib/matplotlib/backend_bases.py
+++ b/lib/matplotlib/backend_bases.py
@@ -1190,6 +1190,7 @@ class CloseEvent(Event):
def __init__(self, name, canvas, guiEvent=None):
Event.__init__(self, name, canvas, guiEvent)
+
class LocationEvent(Event):
"""
An event that has a screen location
@@ -1295,9 +1296,6 @@ def _update_enter_leave(self):
LocationEvent.lastevent = self
-
-
-
class MouseEvent(LocationEvent):
"""
A mouse event ('button_press_event', 'button_release_event', 'scroll_event',
@@ -1307,10 +1305,12 @@ class MouseEvent(LocationEvent):
attributes, the following attributes are defined:
*button*
- button pressed None, 1, 2, 3, 'up', 'down' (up and down are used for scroll events)
+ button pressed None, 1, 2, 3, 'up', 'down' (up and down are used
+ for scroll events)
*key*
- the key pressed: None, chr(range(255), 'shift', 'win', or 'control'
+ the key depressed when the mouse event triggered (see
+ :class:`KeyEvent`)
*step*
number of scroll steps (positive for 'up', negative for 'down')
@@ -1319,7 +1319,7 @@ class MouseEvent(LocationEvent):
Example usage::
def on_press(event):
- print 'you pressed', event.button, event.xdata, event.ydata
+ print('you pressed', event.button, event.xdata, event.ydata)
cid = fig.canvas.mpl_connect('button_press_event', on_press)
@@ -1346,8 +1346,10 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
self.dblclick = dblclick
def __str__(self):
- return "MPL MouseEvent: xy=(%d,%d) xydata=(%s,%s) button=%d dblclick=%s inaxes=%s"%\
- (self.x,self.y,str(self.xdata),str(self.ydata),self.button,self.dblclick,self.inaxes)
+ return ("MPL MouseEvent: xy=(%d,%d) xydata=(%s,%s) button=%d " +
+ "dblclick=%s inaxes=%s") % (self.x, self.y, self.xdata,
+ self.ydata, self.button, self.dblclick, self.inaxes)
+
class PickEvent(Event):
"""
@@ -1377,7 +1379,7 @@ def on_pick(event):
thisline = event.artist
xdata, ydata = thisline.get_data()
ind = event.ind
- print 'on pick line:', zip(xdata[ind], ydata[ind])
+ print('on pick line:', zip(xdata[ind], ydata[ind]))
cid = fig.canvas.mpl_connect('pick_event', on_pick)
@@ -1400,16 +1402,23 @@ class KeyEvent(LocationEvent):
attributes, the following attributes are defined:
*key*
- the key pressed: None, chr(range(255), shift, win, or control
-
- This interface may change slightly when better support for
- modifier keys is included.
-
-
+ the key(s) pressed. Could be **None**, a single case sensitive ascii
+ character ("g", "G", "#", etc.), a special key
+ ("control", "shift", "f1", "up", etc.) or a
+ combination of the above (e.g. "ctrl+alt+g", "ctrl+alt+G").
+
+ .. note::
+
+ Modifier keys will be prefixed to the pressed key and will be in the
+ order "ctrl", "alt", "super". The exception to this rule is when the
+ pressed key is itself a modifier key, therefore "ctrl+alt" and
+ "alt+control" can both be valid key values.
+
+
Example usage::
def on_key(event):
- print 'you pressed', event.key, event.xdata, event.ydata
+ print('you pressed', event.key, event.xdata, event.ydata)
cid = fig.canvas.mpl_connect('key_press_event', on_key)
@@ -1419,7 +1428,6 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
self.key = key
-
class FigureCanvasBase(object):
"""
The canvas the figure renders into.
@@ -1448,7 +1456,6 @@ class FigureCanvasBase(object):
'close_event'
]
-
def __init__(self, figure):
figure.set_canvas(self)
self.figure = figure
@@ -1657,7 +1664,8 @@ def button_press_event(self, x, y, button, dblclick=False, guiEvent=None):
"""
self._button = button
s = 'button_press_event'
- mouseevent = MouseEvent(s, self, x, y, button, self._key, dblclick=dblclick, guiEvent=guiEvent)
+ mouseevent = MouseEvent(s, self, x, y, button, self._key,
+ dblclick=dblclick, guiEvent=guiEvent)
self.callbacks.process(s, mouseevent)
def button_release_event(self, x, y, button, guiEvent=None):
@@ -1743,7 +1751,7 @@ def enter_notify_event(self, guiEvent=None, xy=None):
self.callbacks.process('figure_enter_event', event)
def idle_event(self, guiEvent=None):
- 'call when GUI is idle'
+ """Called when GUI is idle."""
s = 'idle_event'
event = IdleEvent(s, self, guiEvent=guiEvent)
self.callbacks.process(s, event)
@@ -1789,7 +1797,7 @@ def draw_cursor(self, event):
def get_width_height(self):
"""
- return the figure width and height in points or pixels
+ Return the figure width and height in points or pixels
(depending on the backend), truncated to integers
"""
return int(self.figure.bbox.width), int(self.figure.bbox.height)
@@ -1911,7 +1919,6 @@ def get_supported_filetypes_grouped(self):
groupings[name].sort()
return groupings
-
def _get_print_method(self, format):
method_name = 'print_%s' % format
@@ -1936,7 +1943,6 @@ def _print_method(*args, **kwargs):
return getattr(self, method_name)
-
def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
orientation='portrait', format=None, **kwargs):
"""
@@ -2078,9 +2084,6 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
#self.figure.canvas.draw() ## seems superfluous
return result
-
-
-
def get_default_filetype(self):
"""
Get the default savefig file format as specified in rcParam
@@ -2099,7 +2102,7 @@ def set_window_title(self, title):
def switch_backends(self, FigureCanvasClass):
"""
- instantiate an instance of FigureCanvasClass
+ Instantiate an instance of FigureCanvasClass
This is used for backend switching, eg, to instantiate a
FigureCanvasPS from a FigureCanvasGTK. Note, deep copying is
@@ -2148,7 +2151,7 @@ def func(event)
Example usage::
def on_press(event):
- print 'you pressed', event.button, event.xdata, event.ydata
+ print('you pressed', event.button, event.xdata, event.ydata)
cid = canvas.mpl_connect('button_press_event', on_press)
@@ -2158,7 +2161,7 @@ def on_press(event):
def mpl_disconnect(self, cid):
"""
- disconnect callback id cid
+ Disconnect callback id cid
Example usage::
@@ -2274,9 +2277,6 @@ def key_press_handler(event, canvas, toolbar=None):
"""
# these bindings happen whether you are over an axes or not
- #if event.key == 'q':
- # self.destroy() # how cruel to have to destroy oneself!
- # return
if event.key is None:
return
@@ -2289,6 +2289,7 @@ def key_press_handler(event, canvas, toolbar=None):
pan_keys = rcParams['keymap.pan']
zoom_keys = rcParams['keymap.zoom']
save_keys = rcParams['keymap.save']
+ quit_keys = rcParams['keymap.quit']
grid_keys = rcParams['keymap.grid']
toggle_yscale_keys = rcParams['keymap.yscale']
toggle_xscale_keys = rcParams['keymap.xscale']
@@ -2298,6 +2299,10 @@ def key_press_handler(event, canvas, toolbar=None):
if event.key in fullscreen_keys:
canvas.manager.full_screen_toggle()
+ # quit the figure (defaut key 'ctrl+w')
+ if event.key in quit_keys:
+ Gcf.destroy_fig(canvas.figure)
+
if toolbar is not None:
# home or reset mnemonic (default key 'h', 'home' and 'r')
if event.key in home_keys:
@@ -2322,7 +2327,8 @@ def key_press_handler(event, canvas, toolbar=None):
if event.inaxes is None:
return
- # the mouse has to be over an axes to trigger these
+ # these bindings require the mouse to be over an axes to trigger
+
# switching on/off a grid in current axes (default key 'g')
if event.key in grid_keys:
event.inaxes.grid()
@@ -2387,16 +2393,16 @@ def __init__(self, canvas, num):
def destroy(self):
pass
- def full_screen_toggle (self):
+ def full_screen_toggle(self):
pass
def resize(self, w, h):
- 'For gui backends: resize window in pixels'
+ """"For gui backends, resize the window (in pixels)."""
pass
def key_press(self, event):
"""
- implement the default mpl key bindings defined at
+ Implement the default mpl key bindings defined at
:ref:`key-event-handling`
"""
key_press_handler(event, self.canvas, self.canvas.toolbar)
@@ -2414,13 +2420,13 @@ def set_window_title(self, title):
"""
pass
-# cursors
-class Cursors: #namespace
+
+class Cursors:
+ # this class is only used as a simple namespace
HAND, POINTER, SELECT_REGION, MOVE = range(4)
cursors = Cursors()
-
class NavigationToolbar2(object):
"""
Base class for the navigation cursor, version 2
@@ -2464,6 +2470,25 @@ class NavigationToolbar2(object):
That's it, we'll do the rest!
"""
+
+ # list of toolitems to add to the toolbar, format is:
+ # (
+ # text, # the text of the button (often not visible to users)
+ # tooltip_text, # the tooltip shown on hover (where possible)
+ # image_file, # name of the image for the button (without the extension)
+ # name_of_method, # name of the method in NavigationToolbar2 to call
+ # )
+ toolitems = (
+ ('Home', 'Reset original view', 'home', 'home'),
+ ('Back', 'Back to previous view', 'back', 'back'),
+ ('Forward', 'Forward to next view', 'forward', 'forward'),
+ (None, None, None, None),
+ ('Pan', 'Pan axes with left mouse, zoom with right', 'move', 'pan'),
+ ('Zoom', 'Zoom to rectangle', 'zoom_to_rect', 'zoom'),
+ (None, None, None, None),
+ ('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'),
+ ('Save', 'Save the figure', 'filesave', 'save_figure'),
+ )
def __init__(self, canvas):
self.canvas = canvas
@@ -2488,11 +2513,11 @@ def __init__(self, canvas):
self.set_history_buttons()
def set_message(self, s):
- 'display a message on toolbar or in status bar'
+ """Display a message on toolbar or in status bar"""
pass
def back(self, *args):
- 'move back up the view lim stack'
+ """move back up the view lim stack"""
self._views.back()
self._positions.back()
self.set_history_buttons()
@@ -2502,18 +2527,18 @@ def dynamic_update(self):
pass
def draw_rubberband(self, event, x0, y0, x1, y1):
- 'draw a rectangle rubberband to indicate zoom limits'
+ """Draw a rectangle rubberband to indicate zoom limits"""
pass
def forward(self, *args):
- 'move forward in the view lim stack'
+ """Move forward in the view lim stack"""
self._views.forward()
self._positions.forward()
self.set_history_buttons()
self._update_view()
def home(self, *args):
- 'restore the original view'
+ """Restore the original view"""
self._views.home()
self._positions.home()
self.set_history_buttons()
@@ -2542,8 +2567,6 @@ class implementation.
raise NotImplementedError
def mouse_move(self, event):
- #print 'mouse_move', event.button
-
if not event.inaxes or not self._active:
if self._lastCursor != cursors.POINTER:
self.set_cursor(cursors.POINTER)
@@ -2561,9 +2584,10 @@ def mouse_move(self, event):
if event.inaxes and event.inaxes.get_navigate():
- try: s = event.inaxes.format_coord(event.xdata, event.ydata)
- except ValueError: pass
- except OverflowError: pass
+ try:
+ s = event.inaxes.format_coord(event.xdata, event.ydata)
+ except (ValueError, OverflowError):
+ pass
else:
if len(self.mode):
self.set_message('%s, %s' % (self.mode, s))
@@ -2572,7 +2596,7 @@ def mouse_move(self, event):
else: self.set_message(self.mode)
def pan(self,*args):
- 'Activate the pan/zoom tool. pan with left button, zoom with right'
+ """Activate the pan/zoom tool. pan with left button, zoom with right"""
# set the pointer icon and button press funcs to the
# appropriate callbacks
@@ -2604,11 +2628,11 @@ def pan(self,*args):
self.set_message(self.mode)
def press(self, event):
- 'this will be called whenver a mouse button is pressed'
+ """Called whenver a mouse button is pressed."""
pass
def press_pan(self, event):
- 'the press mouse button in pan/zoom mode callback'
+ """the press mouse button in pan/zoom mode callback"""
if event.button == 1:
self._button_pressed=1
@@ -2636,7 +2660,7 @@ def press_pan(self, event):
self.press(event)
def press_zoom(self, event):
- 'the press mouse button in zoom to rect mode callback'
+ """the press mouse button in zoom to rect mode callback"""
if event.button == 1:
self._button_pressed=1
elif event.button == 3:
@@ -2658,17 +2682,14 @@ def press_zoom(self, event):
a.transData.frozen() ))
id1 = self.canvas.mpl_connect('motion_notify_event', self.drag_zoom)
-
id2 = self.canvas.mpl_connect('key_press_event',
self._switch_on_zoom_mode)
id3 = self.canvas.mpl_connect('key_release_event',
self._switch_off_zoom_mode)
self._ids_zoom = id1, id2, id3
-
self._zoom_mode = event.key
-
self.press(event)
def _switch_on_zoom_mode(self, event):
@@ -2680,7 +2701,7 @@ def _switch_off_zoom_mode(self, event):
self.mouse_move(event)
def push_current(self):
- 'push the current view limits and position onto the stack'
+ """push the current view limits and position onto the stack"""
lims = []; pos = []
for a in self.canvas.figure.get_axes():
xmin, xmax = a.get_xlim()
@@ -2695,11 +2716,11 @@ def push_current(self):
self.set_history_buttons()
def release(self, event):
- 'this will be called whenever mouse button is released'
+ """this will be called whenever mouse button is released"""
pass
def release_pan(self, event):
- 'the release mouse button callback in pan/zoom mode'
+ """the release mouse button callback in pan/zoom mode"""
if self._button_pressed is None:
return
@@ -2715,7 +2736,7 @@ def release_pan(self, event):
self.draw()
def drag_pan(self, event):
- 'the drag callback in pan/zoom mode'
+ """the drag callback in pan/zoom mode"""
for a, ind in self._xypress:
#safer to use the recorded button at the press than current button:
@@ -2724,7 +2745,7 @@ def drag_pan(self, event):
self.dynamic_update()
def drag_zoom(self, event):
- 'the drag callback in zoom mode'
+ """the drag callback in zoom mode"""
if self._xypress:
x, y = event.x, event.y
@@ -2744,10 +2765,8 @@ def drag_zoom(self, event):
self.draw_rubberband(event, x, y, lastx, lasty)
-
-
def release_zoom(self, event):
- 'the release mouse button callback in zoom to rect mode'
+ """the release mouse button callback in zoom to rect mode"""
for zoom_id in self._ids_zoom:
self.canvas.mpl_disconnect(zoom_id)
self._ids_zoom = []
@@ -2855,7 +2874,7 @@ def release_zoom(self, event):
self.release(event)
def draw(self):
- 'redraw the canvases, update the locators'
+ """Redraw the canvases, update the locators"""
for a in self.canvas.figure.get_axes():
xaxis = getattr(a, 'xaxis', None)
yaxis = getattr(a, 'yaxis', None)
@@ -2871,12 +2890,10 @@ def draw(self):
loc.refresh()
self.canvas.draw()
-
-
def _update_view(self):
- '''update the viewlim and position from the view and
+ """Update the viewlim and position from the view and
position stack for each axes
- '''
+ """
lims = self._views()
if lims is None: return
@@ -2892,9 +2909,8 @@ def _update_view(self):
self.draw()
-
def save_figure(self, *args):
- 'save the current figure'
+ """Save the current figure"""
raise NotImplementedError
def set_cursor(self, cursor):
@@ -2905,13 +2921,13 @@ def set_cursor(self, cursor):
pass
def update(self):
- 'reset the axes stack'
+ """Reset the axes stack"""
self._views.clear()
self._positions.clear()
self.set_history_buttons()
def zoom(self, *args):
- 'activate zoom to rect mode'
+ """Activate zoom to rect mode"""
if self._active == 'ZOOM':
self._active = None
else:
@@ -2938,7 +2954,6 @@ def zoom(self, *args):
self.set_message(self.mode)
-
def set_history_buttons(self):
- 'enable or disable back/forward button'
+ """Enable or disable back/forward button"""
pass
diff --git a/lib/matplotlib/backends/backend_fltkagg.py b/lib/matplotlib/backends/backend_fltkagg.py
index cf0d398854a8..fe31d0f81191 100644
--- a/lib/matplotlib/backends/backend_fltkagg.py
+++ b/lib/matplotlib/backends/backend_fltkagg.py
@@ -136,6 +136,8 @@ def handle(self, event):
self._key=special_key[ikey]
except:
self._key=None
+
+ # TODO: Handle ctrl, alt, super modifiers.
FigureCanvasBase.key_press_event(self._source, self._key)
return 1
elif event == Fltk.FL_KEYUP:
diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py
index e4f6f31742f1..4ca9ca7deb48 100644
--- a/lib/matplotlib/backends/backend_gtk.py
+++ b/lib/matplotlib/backends/backend_gtk.py
@@ -189,6 +189,10 @@ class FigureCanvasGTK (gtk.DrawingArea, FigureCanvasBase):
65455 : '/',
65439 : 'dec',
65421 : 'enter',
+ 65511 : 'super',
+ 65512 : 'super',
+ 65406 : 'alt',
+ 65289 : 'tab',
}
# Setting this as a static constant prevents
@@ -322,16 +326,20 @@ def enter_notify_event(self, widget, event):
def _get_key(self, event):
if event.keyval in self.keyvald:
key = self.keyvald[event.keyval]
- elif event.keyval