I created an application based on Tkinter that uses Matplotlib for plotting a waveform. I wonder how I could change the tooltips for the Matplotlib toolbar buttons (I need to translate the English descriptions since my application is in Czech language). I'd also like to change/translate or just remove the descriptions (pan/zoom
, zoom rect
) that appear next to the toolbar panel when clicking on the zoom or pan button.
I found some useful tips concerning how to add or remove buttons from the toolbar, but haven't found any advice for customizing the tooltips/descriptions. I think it would be similar to the former case in that I'd need to create a new toolbar class based on NavigationToolbar2TkAgg
and modify it in some way. Any advices on how this could be done? Many thanks in advance.
PART 1
So this should be pretty straight forward. The NavigationToolbar2TkAgg
class inherits from NavigationToolbar2
which can be found in matplotlib.backend_bases
. If you look at NavigationToolbar2TkAgg
, you will see that the pop-up text for the buttons is stored in an attribute called self.toolitems
. This attribute is inherited from the base class, where it is defined as:
# 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'), )
The second item in each tuple is the text that is pops up when you mouse-over the button. To override this, just subclass and make your own version of toolitems
.
For example (with filler text):
import numpy as np import Tkinter as tk import matplotlib as mpl from matplotlib.patches import Rectangle from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg # custom toolbar with lorem ipsum text class CustomToolbar(NavigationToolbar2TkAgg): def __init__(self,canvas_,parent_): self.toolitems = ( ('Home', 'Lorem ipsum dolor sit amet', 'home', 'home'), ('Back', 'consectetuer adipiscing elit', 'back', 'back'), ('Forward', 'sed diam nonummy nibh euismod', 'forward', 'forward'), (None, None, None, None), ('Pan', 'tincidunt ut laoreet', 'move', 'pan'), ('Zoom', 'dolore magna aliquam', 'zoom_to_rect', 'zoom'), (None, None, None, None), ('Subplots', 'putamus parum claram', 'subplots', 'configure_subplots'), ('Save', 'sollemnes in futurum', 'filesave', 'save_figure'), ) NavigationToolbar2TkAgg.__init__(self,canvas_,parent_) class MyApp(object): def __init__(self,root): self.root = root self._init_app() # here we embed the a figure in the Tk GUI def _init_app(self): self.figure = mpl.figure.Figure() self.ax = self.figure.add_subplot(111) self.canvas = FigureCanvasTkAgg(self.figure,self.root) self.toolbar = CustomToolbar(self.canvas,self.root) self.toolbar.update() self.plot_widget = self.canvas.get_tk_widget() self.plot_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbar.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.canvas.show() # plot something random def plot(self): self.ax.imshow(np.random.normal(0.,1.,size=[100,100]),cmap="hot",aspect="auto") self.figure.canvas.draw() def main(): root = tk.Tk() app = MyApp(root) app.plot() root.mainloop() if __name__ == "__main__": main()
This should give you a normal embedded matplotlib figure, but when you mouse-over the buttons you will get something like:
PART 2
The second part of the question is less elegant. The text for "pan/zoom" and "zoom rect" is hardcoded into the pan
and zoom
methods of the toolbar. The actual text is held in the self.mode
attribute of the toolbar. The easiest way to overwrite what this produces is to make subclass wrappers for the baseclass pan
and zoom
methods.
These wrappers go in the CustomToolbar
class from above like:
def pan(self): NavigationToolbar2TkAgg.pan(self) self.mode = "I'm panning!" #<--- whatever you want to replace "pan/zoom" goes here self.set_message(self.mode) def zoom(self): NavigationToolbar2TkAgg.zoom(self) self.mode = "I'm zooming!" #<--- whatever you want to replace "zoom rect" goes here self.set_message(self.mode)
This is just one way to do this, another might be to wrap the set_message
method to catch and translate specific bits of text.