Matplotlib/Tkinter - 自定义工具栏提示

3 投票
1 回答
10620 浏览
提问于 2025-04-18 03:24

我创建了一个基于Tkinter的应用程序,使用Matplotlib来绘制波形。我想知道如何更改Matplotlib工具栏按钮的提示信息(因为我的应用是捷克语的,所以需要把英文描述翻译成捷克语)。我还想更改或翻译,或者干脆去掉在点击缩放或平移按钮时出现在工具栏旁边的描述(比如pan/zoomzoom rect)。

我找到了一些关于如何添加或移除工具栏按钮的有用提示,但没有找到关于自定义提示信息或描述的建议。我觉得这可能和之前的情况类似,我需要基于NavigationToolbar2TkAgg创建一个新的工具栏类,并以某种方式进行修改。有没有什么建议可以帮我实现这个?非常感谢!

1 个回答

12

第一部分

这个问题应该比较简单。NavigationToolbar2TkAgg 这个类是从 NavigationToolbar2 继承而来的,而 NavigationToolbar2 可以在 matplotlib.backend_bases 中找到。如果你查看 NavigationToolbar2TkAgg,你会发现按钮的弹出提示文本存储在一个叫 self.toolitems 的属性里。这个属性是从父类继承过来的,在父类中是这样定义的:

# 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'),
    )

每个元组中的第二个项目就是当你把鼠标悬停在按钮上时弹出的文本。要想修改这个文本,只需要创建一个子类,并自定义自己的 toolitems

举个例子(这里用的是填充文本):

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()

这样你就能得到一个正常嵌入的 matplotlib 图形,但当你把鼠标悬停在按钮上时,会看到类似这样的内容:

自定义工具栏文本示例

第二部分

问题的第二部分就没那么优雅了。“平移/缩放”和“缩放矩形”的文本是硬编码在工具栏的 panzoom 方法里的。实际的文本保存在工具栏的 self.mode 属性中。要想覆盖这些文本,最简单的方法是为父类的 panzoom 方法创建子类包装器。

这些包装器可以放在上面提到的 CustomToolbar 类中,像这样:

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)

这只是一种方法,另一种方法可能是包装 set_message 方法,以捕捉并翻译特定的文本。

撰写回答