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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12695678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:37:26  来源:igfitidea点击:

How to modify the navigation toolbar easily in a matplotlib figure window?

pythonmatplotlib

提问by JBT

Is it possible to do something like the following to modify the navigation toolbar in matplotlib?

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

  1. Generate a figure window, with: fig = figure()
  2. Get a reference of the navigation tool-bar, with: tbar = fig.get_navigation_toolbar(), or better yet, just by: tbar = fig.navtbar
  3. Modify the tool-bar through the reference tbar, such as delete/add/edit a button with something like this:
       tbar.add_button(<a Button object>);
       tbar.remove_button(a reference to a button);
       tbar.edit_button(a reference to a button);
  4. Update the figure with: fig.canvas.draw()
  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()

Thank you very much.

非常感谢。

采纳答案by torfbolt

The way I found to remove unwanted toolbar items is making a subclass, which is instantiated and used in a GTK application. As I manually create Figure, FigureCanvas and NavigationToolbar objects anyway, this was the easiest way.

我发现删除不需要的工具栏项目的方法是创建一个子类,它被实例化并在 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')]

If you want to create custom buttons, you should take a look on the definition of NavigationToolbar2in backend_bases. You can easily add your own entries to the toolitemslist and define appropriate callback functions in your toolbar subclass.

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

回答by user2304916

With MPL 1.2.1 it is possible to get an handler of the navigation toolbar of a standard MPL figure through figure.canvas.toolbar. I'm not sure about previous versions.

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

At least with the QT backend it is possible to add arbitrary widgets to the navigation toolbar using the QT method .addWidget(). I suppose other backends will work using similar methods, but I haven't tested them.

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

Here it is a working example (using the QT backend) that adds a QLineEdit()to the navigation toolbar to change the title of a MPL figure (run from IPython (pylab) with run -i ..., then launch test()):

这是一个工作示例(使用 QT 后端),它QLineEdit()向导航工具栏添加 以更改 MPL 图的标题(从 IPython (pylab) 运行,使用run -i ...,然后启动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()

回答by MadeOfAir

In addition to torfbotl's solution above, you might have an extra button hanging at the end (the one with the green check mark).

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

That can be mitigated in the subclass constructor:

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

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

回答by glep

The previous answers work but are very backend-specific. A slighly more elegant solution is to subclass NavigationToolbar2, as done in this other answer: Matplotlib/Tkinter - customizing toolbar tooltipsThere the aim was to change the tooltips, but adding or removing a button is equally trivial.

以前的答案有效,但非常特定于后端。一个稍微更优雅的解决方案是将 NavigationToolbar2 子类化,就像在另一个答案中所做的那样:Matplotlib/Tkinter - 自定义工具栏工具提示目的是更改工具提示,但添加或删除按钮同样微不足道。

回答by Donald

I found that just that

我发现只是这样

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

worked to remove all tools, and popping individual tools worked too. That said,

努力删除所有工具,弹出单个工具也有效。那说,

toolbar.toolitems=[]

didnt work, so the code must have another reference to this array somewhere.

没有工作,所以代码必须在某处有另一个对该数组的引用。

回答by Nqsir

Using PyQt5 and matplotlib version '3.0.2'

使用 PyQt5 和 matplotlib 版本 '3.0.2'

If you want to add some buttons just follow the doc given by the class NavigationToolbar2() that is initialised in NavigationToolbar2QT() wich is imported from matplotlib.backends.backend_qt5agg :

如果您想添加一些按钮,只需遵循 NavigationToolbar2() 类给出的文档,该类在 NavigationToolbar2QT() 中初始化,从 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
# )

So you need to redefine your class as previously said (you can also see under, the pre-defined buttons available atm). In my case I wanted to remove 2 buttons ('Save' and 'Subplots' that I commented) so that gave me :

因此,您需要像之前所说的那样重新定义您的类(您还可以在下面看到 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'),
    )

And calling the NavigationToolbar2QT (still in my case) :

并调用 NavigationToolbar2QT (仍然在我的情况下):

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