如何在matplotlib图窗口中轻松修改导航工具栏?

时间:2012-10-02 18:00:19

标签: python matplotlib

是否可以执行以下操作来修改matplotlib中的导航工具栏?

  1. 生成一个图形窗口,其中包含:fig = figure()
  2. 获取导航工具栏的参考,其中包含:tbar = fig.get_navigation_toolbar(), 或者更好,只需:tbar = fig.navtbar
  3. 通过参考tbar修改工具栏,例如删除/添加/编辑按钮,如下所示:
    tbar.add_button(<a Button object>);
    tbar.remove_button(a reference to a button);
    tbar.edit_button(a reference to a button);
  4. 使用以下内容更新图:fig.canvas.draw()
  5. 非常感谢。

6 个答案:

答案 0 :(得分:19)

我发现删除不需要的工具栏项的方法是创建一个子类,它在GTK应用程序中实例化并使用。当我手动创建Figure,FigureCanvas和NavigationToolbar对象时,这是最简单的方法。

class NavigationToolbar(NavigationToolbar2GTKAgg):
    # only display the buttons we need
    toolitems = [t for t in NavigationToolbar2GTKAgg.toolitems if
                 t[0] in ('Home', 'Pan', 'Zoom', 'Save')]

如果要创建自定义按钮,您应该查看backend_bases中NavigationToolbar2的定义。您可以轻松地将自己的条目添加到toolitems列表中,并在工具栏子类中定义适当的回调函数。

答案 1 :(得分:7)

使用MPL 1.2.1,可以通过figure.canvas.toolbar获得标准MPL数字导航工具栏的处理程序。我不确定以前的版本。

至少使用QT后端,可以使用QT方法.addWidget()将任意小部件添加到导航工具栏。我想其他后端将使用类似的方法,但我还没有对它们进行测试。

这是一个工作示例(使用QT后端),将QLineEdit()添加到导航工具栏以更改MPL图形的标题(使用run -i ...从IPython(pylab)运行,然后启动test()):

from PySide import QtGui, QtCore

def test():
    plot([1,2,3], lw=2)
    q = qt4_interface(gcf())
    return q   # WARNING: it's paramount to return the object otherwise, with 
               # no references, python deletes it and the GUI doesn't respond!

class qt4_interface:
    def __init__(self,fig):
        self.fig = fig

        toolbar = fig.canvas.toolbar
        self.line_edit = QtGui.QLineEdit()
        toolbar.addWidget(self.line_edit)
        self.line_edit.editingFinished.connect(self.do_something) 

    def do_something(self, *args):
        self.fig.axes[0].set_title(self.line_edit.text())
        self.fig.canvas.draw()
        #f = open('l','a'); f.write('yes\n'); f.flush(); f.close()

答案 2 :(得分:2)

之前的答案有效,但非常适合后端。一个更优雅的解决方案是子类化NavigationToolbar2,就像在另一个答案中所做的那样:Matplotlib/Tkinter - customizing toolbar tooltips 目标是更改工具提示,但添加或删除按钮同样微不足道。

答案 3 :(得分:1)

除了上面的torfbotl解决方案之外,您可能还会在末尾悬挂一个额外的按钮(带有绿色复选标记的按钮)。

可以在子类构造函数中缓解:

from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar

class PanOnlyToolbar(NavigationToolbar):
    # only display the buttons we need
    toolitems = [t for t in NavigationToolbar2GTKAgg.toolitems if
                 t[0] in ("Pan", )]

    def __init__(self, *args, **kwargs):
        super(PanOnlyToolbar, self).__init__(*args, **kwargs)
        self.layout().takeAt(1)  #or more than 1 if you have more buttons

答案 4 :(得分:1)

使用PyQt5和matplotlib版本“ 3.0.2”

如果要添加一些按钮,请遵循NavigationToolbar2QT()中初始化的类NavigationToolbar2()给出的文档,该文档是从matplotlib.backends.backend_qt5agg导入的:

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

因此,您需要如前所述重新定义类(您还可以在atm的预定义按钮下看到)。就我而言,我想删除2个按钮(我评论过的“保存”和“子情节”),这样我就可以了:

class NavigationToolbar2QT(NavigationToolbar2QT):
    # only display the buttons we need
    NavigationToolbar2QT.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'),
        # ('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'),
        (None, None, None, None),
        # ('Save', 'Save the figure', 'filesave', 'save_figure'),
    )

并调用NavigationToolbar2QT(在我来说仍然如此):

figure = plt.figure()
canvas = FigureCanvas(figure)
toolbar = NavigationToolbar2QT(canvas, self)

答案 5 :(得分:0)

我发现就是这样

fig = plt.figure()
toolbar = fig.canvas.manager.toolbar
tb=toolbar.toolitems
while len(tb)>0:
    tb.pop(0)

致力于删除所有工具,弹出单个工具也起作用。就是这样,

toolbar.toolitems=[]

尽力而为,因此代码必须在某处对该数组进行另一个引用。