Skip to content

Commit e6a4e1e

Browse files
committed
example working with Tk
1 parent 5056729 commit e6a4e1e

File tree

5 files changed

+148
-173
lines changed

5 files changed

+148
-173
lines changed
+30-24
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,40 @@
11
import matplotlib
2-
# matplotlib.use('GTK3Cairo')
3-
matplotlib.use('TkAGG')
2+
matplotlib.use('GTK3Cairo')
3+
# matplotlib.use('TkAGG')
44
matplotlib.rcParams['toolbar'] = 'navigation'
55
import matplotlib.pyplot as plt
66
from matplotlib.backend_tools import ToolBase
77

88

9-
#Create a simple tool to list all the tools
9+
# Create a simple tool to list all the tools
1010
class ListTools(ToolBase):
11-
#keyboard shortcut
11+
# keyboard shortcut
1212
keymap = 'm'
13-
#Name used as id, must be unique between tools of the same navigation
14-
name = 'List'
1513
description = 'List Tools'
16-
#Where to put it in the toolbar, -1 = at the end, None = Not in toolbar
17-
position = -1
1814

1915
def trigger(self, event):
20-
#The most important attributes are navigation and figure
21-
self.navigation.list_tools()
22-
23-
24-
#A simple example of copy canvas
25-
#ref: at https://github.com/matplotlib/matplotlib/issues/1987
26-
class CopyTool(ToolBase):
16+
tools = self.navigation.get_tools()
17+
18+
print ('_' * 80)
19+
print ("{0:12} {1:45} {2}".format('Name (id)',
20+
'Tool description',
21+
'Keymap'))
22+
print ('_' * 80)
23+
for name in sorted(tools.keys()):
24+
keys = ', '.join(sorted(tools[name]['keymap']))
25+
print ("{0:12} {1:45} {2}".format(name,
26+
tools[name]['description'],
27+
keys))
28+
print ('_' * 80)
29+
30+
31+
# A simple example of copy canvas
32+
# ref: at https://github.com/matplotlib/matplotlib/issues/1987
33+
class CopyToolGTK3(ToolBase):
2734
keymap = 'ctrl+c'
28-
name = 'Copy'
2935
description = 'Copy canvas'
30-
position = -1
36+
# It is not added to the toolbar as a button
37+
intoolbar = False
3138

3239
def trigger(self, event):
3340
from gi.repository import Gtk, Gdk
@@ -41,13 +48,12 @@ def trigger(self, event):
4148
fig = plt.figure()
4249
plt.plot([1, 2, 3])
4350

44-
#If we are in the old toolbar, don't try to modify it
45-
if matplotlib.rcParams['toolbar'] in ('navigation', 'None'):
46-
##Add the custom tools that we created
47-
fig.canvas.manager.navigation.add_tool(ListTools)
48-
fig.canvas.manager.navigation.add_tool(CopyTool)
51+
# Add the custom tools that we created
52+
fig.canvas.manager.navigation.add_tool('List', ListTools)
53+
if matplotlib.rcParams['backend'] == 'GTK3Cairo':
54+
fig.canvas.manager.navigation.add_tool('copy', CopyToolGTK3)
4955

50-
##Just for fun, lets remove the back button
51-
fig.canvas.manager.navigation.remove_tool('Back')
56+
# Just for fun, lets remove the back button
57+
fig.canvas.manager.navigation.remove_tool('Back')
5258

5359
plt.show()

lib/matplotlib/backend_bases.py

+35-75
Original file line numberDiff line numberDiff line change
@@ -3230,41 +3230,27 @@ class NavigationBase(object):
32303230
32313231
Attributes
32323232
----------
3233-
canvas : `FigureCanvas` instance
3233+
manager : `FigureManager` instance
32343234
toolbar : `Toolbar` instance that is controlled by this `Navigation`
32353235
keypresslock : `LockDraw` to know if the `canvas` key_press_event is
32363236
locked
32373237
messagelock : `LockDraw` to know if the message is available to write
32383238
"""
32393239

32403240
_default_cursor = cursors.POINTER
3241-
_default_tools = [tools.ToolToggleGrid,
3242-
tools.ToolToggleFullScreen,
3243-
tools.ToolQuit,
3244-
tools.ToolEnableAllNavigation,
3245-
tools.ToolEnableNavigation,
3246-
tools.ToolToggleXScale,
3247-
tools.ToolToggleYScale,
3248-
tools.ToolHome, tools.ToolBack,
3249-
tools.ToolForward,
3250-
None,
3251-
tools.ToolZoom,
3252-
tools.ToolPan,
3253-
None,
3254-
'ConfigureSubplots',
3255-
'SaveFigure']
3256-
3257-
def __init__(self, canvas, toolbar=None):
3241+
3242+
def __init__(self, manager):
32583243
""".. automethod:: _toolbar_callback"""
32593244

3260-
self.canvas = canvas
3261-
self.toolbar = self._get_toolbar(toolbar, canvas)
3245+
self.manager = manager
3246+
self.canvas = manager.canvas
3247+
self.toolbar = manager.toolbar
32623248

3263-
self._key_press_handler_id = self.canvas.mpl_connect('key_press_event',
3264-
self._key_press)
3249+
self._key_press_handler_id = self.canvas.mpl_connect(
3250+
'key_press_event', self._key_press)
32653251

3266-
self._idDrag = self.canvas.mpl_connect('motion_notify_event',
3267-
self._mouse_move)
3252+
self._idDrag = self.canvas.mpl_connect(
3253+
'motion_notify_event', self._mouse_move)
32683254

32693255
# a dict from axes index to a list of view limits
32703256
self.views = cbook.Stack()
@@ -3280,36 +3266,15 @@ def __init__(self, canvas, toolbar=None):
32803266
# to write into toolbar message
32813267
self.messagelock = widgets.LockDraw()
32823268

3283-
for tool in self._default_tools:
3269+
for name, tool in tools.tools:
32843270
if tool is None:
32853271
if self.toolbar is not None:
32863272
self.toolbar.add_separator(-1)
32873273
else:
3288-
self.add_tool(tool)
3274+
self.add_tool(name, tool, None)
32893275

32903276
self._last_cursor = self._default_cursor
32913277

3292-
@classmethod
3293-
def get_default_tools(cls):
3294-
"""Get the default tools"""
3295-
3296-
return cls._default_tools
3297-
3298-
@classmethod
3299-
def set_default_tools(cls, tools):
3300-
"""Set default tools"""
3301-
3302-
cls._default_tools = tools
3303-
3304-
def _get_toolbar(self, toolbar, canvas):
3305-
# must be inited after the window, drawingArea and figure
3306-
# attrs are set
3307-
if rcParams['toolbar'] == 'navigation' and toolbar is not None:
3308-
toolbar = toolbar(canvas.manager)
3309-
else:
3310-
toolbar = None
3311-
return toolbar
3312-
33133278
@property
33143279
def active_toggle(self):
33153280
"""Toggled Tool
@@ -3381,8 +3346,7 @@ def unregister(self, name):
33813346
This method is used by `PersistentTools` to remove the reference kept
33823347
by `Navigation`.
33833348
3384-
It is usually called by the `deactivate` method or during
3385-
destroy if it is a graphical Tool.
3349+
It is usually called by the `unregister` method
33863350
33873351
If called, next time the `Tool` is used it will be reinstantiated
33883352
instead of using the existing instance.
@@ -3411,29 +3375,27 @@ def remove_tool(self, name):
34113375
if self.toolbar:
34123376
self.toolbar._remove_toolitem(name)
34133377

3414-
def add_tool(self, tool):
3378+
def add_tool(self, name, tool, position=None):
34153379
"""Add tool to `Navigation`
34163380
34173381
Parameters
34183382
----------
3383+
name : string
3384+
Name of the tool, treated as the ID, has to be unique
34193385
tool : string or `Tool` class
34203386
Reference to find the class of the Tool to be added
3387+
position : int or None (default)
3388+
Position in the toolbar, if None, is positioned at the end
34213389
"""
34223390

34233391
tool_cls = self._get_cls_to_instantiate(tool)
34243392
if tool_cls is False:
34253393
warnings.warn('Impossible to find class for %s' % str(tool))
34263394
return
3427-
name = tool_cls.name
34283395

3429-
if name is None:
3430-
warnings.warn('tool_clss need a name to be added, it is used '
3431-
'as ID')
3432-
return
34333396
if name in self._tools:
34343397
warnings.warn('A tool_cls with the same name already exist, '
34353398
'not added')
3436-
34373399
return
34383400

34393401
self._tools[name] = tool_cls
@@ -3444,7 +3406,7 @@ def add_tool(self, tool):
34443406
(k, self._keys[k], name))
34453407
self._keys[k] = name
34463408

3447-
if self.toolbar and tool_cls.position is not None:
3409+
if self.toolbar and tool_cls.intoolbar:
34483410
# TODO: better search for images, they are not always in the
34493411
# datapath
34503412
basedir = os.path.join(rcParams['datapath'], 'images')
@@ -3453,10 +3415,11 @@ def add_tool(self, tool):
34533415
else:
34543416
fname = None
34553417
toggle = issubclass(tool_cls, tools.ToolToggleBase)
3456-
self.toolbar._add_toolitem(name, tool_cls.description,
3457-
fname,
3458-
tool_cls.position,
3459-
toggle)
3418+
self.toolbar._add_toolitem(name,
3419+
tool_cls.description,
3420+
fname,
3421+
position,
3422+
toggle)
34603423

34613424
def _get_cls_to_instantiate(self, callback_class):
34623425
if isinstance(callback_class, six.string_types):
@@ -3505,7 +3468,7 @@ def _key_press(self, event):
35053468

35063469
def _get_instance(self, name):
35073470
if name not in self._instances:
3508-
instance = self._tools[name](self.canvas.figure)
3471+
instance = self._tools[name](self.canvas.figure, name)
35093472
# register instance
35103473
self._instances[name] = instance
35113474

@@ -3551,26 +3514,23 @@ def _handle_toggle(self, name, event=None, from_toolbar=False):
35513514
for a in self.canvas.figure.get_axes():
35523515
a.set_navigate_mode(self._toggled)
35533516

3554-
def list_tools(self):
3555-
"""Print the list the tools controlled by `Navigation`"""
3517+
def get_tools(self):
3518+
"""Return the tools controlled by `Navigation`"""
35563519

3557-
print ('_' * 80)
3558-
print ("{0:20} {1:50} {2}".format('Name (id)', 'Tool description',
3559-
'Keymap'))
3560-
print ('_' * 80)
3520+
d = {}
35613521
for name in sorted(self._tools.keys()):
35623522
tool = self._tools[name]
35633523
keys = [k for k, i in six.iteritems(self._keys) if i == name]
3564-
print ("{0:20} {1:50} {2}".format(tool.name, tool.description,
3565-
', '.join(keys)))
3566-
print ('_' * 80, '\n')
3524+
d[name] = {'cls': tool,
3525+
'description': tool.description,
3526+
'keymap': keys}
3527+
return d
35673528

35683529
def update(self):
35693530
"""Reset the axes stack"""
35703531

35713532
self.views.clear()
35723533
self.positions.clear()
3573-
# self.set_history_buttons()
35743534

35753535
def _mouse_move(self, event):
35763536
if not event.inaxes or not self._toggled:
@@ -3667,7 +3627,6 @@ def push_current(self):
36673627
a.get_position().frozen()))
36683628
self.views.push(lims)
36693629
self.positions.push(pos)
3670-
# self.set_history_buttons()
36713630

36723631
def draw_rubberband(self, event, caller, x0, y0, x1, y1):
36733632
"""Draw a rectangle rubberband to indicate zoom limits
@@ -3719,7 +3678,7 @@ def __init__(self, manager):
37193678
self.manager = manager
37203679

37213680
def _add_toolitem(self, name, description, image_file, position,
3722-
toggle):
3681+
toggle):
37233682
"""Add a toolitem to the toolbar
37243683
37253684
The callback associated with the button click event,
@@ -3776,7 +3735,8 @@ def _toggle(self, name, callback=False):
37763735
37773736
"""
37783737

3779-
# carefull, callback means to perform or not the callback while toggling
3738+
# carefull, callback means to perform or not the callback while
3739+
# toggling
37803740
raise NotImplementedError
37813741

37823742
def _remove_toolitem(self, name):

0 commit comments

Comments
 (0)