Как легко изменить панель навигации в окне фигуры matplotlib?

Возможно ли сделать что-то вроде следующего, чтобы изменить панель навигации в matplotlib?

  • Создайте окно фигуры с помощью: fig = figure()
  • Получить ссылку на панель инструментов навигации с помощью: tbar = fig.get_navigation_toolbar(), или еще лучше, просто: tbar = fig.navtbar
  • Измените панель инструментов с помощью ссылки tbar, например, удалите/добавьте/отредактируйте кнопку с чем-то вроде этого:
      tbar.add_button(<a Button object>);
      tbar.remove_button(a reference to a button);
      tbar.edit_button(a reference to a button);
  • Обновите фигуру с помощью fig.canvas.draw()

Большое спасибо.

Ответ 1

Как я нашел, чтобы удалить ненужные элементы панели инструментов, создается подкласс, который создается и используется в приложении 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')]

Если вы хотите создать пользовательские кнопки, вы должны взглянуть на определение NavigationToolbar2 в backend_bases. Вы можете легко добавить свои собственные записи в список toolitems и определить соответствующие функции обратного вызова в подклассе панели инструментов.

Ответ 2

С MPL 1.2.1 можно получить обработчик панели навигации стандартной фигуры MPL через figure.canvas.toolbar. Я не уверен в предыдущих версиях.

По крайней мере, с помощью QT-сервера можно добавить произвольные виджеты на панель навигации с помощью метода QT .addWidget(). Я полагаю, что другие бэкенды будут работать с использованием подобных методов, но я их не тестировал.

Здесь приведен рабочий пример (с использованием бэкэнда 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 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()

Ответ 3

Предыдущие ответы работают, но очень специфичны для бэкэнд. Более элегантным решением является подкласс NavToolbar2, как это сделано в этом другом ответе: Matplotlib/Tkinter - настраиваемые всплывающие подсказки панели инструментов Целью было изменить всплывающие подсказки, но добавление или удаление кнопки одинаково тривиально.

Ответ 4

В дополнение к решению 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

Ответ 5

Я обнаружил, что только это

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

работал, чтобы удалить все инструменты, и совать отдельные инструменты тоже работали. Это сказало,

toolbar.toolitems=[]

не работает, поэтому код должен иметь другую ссылку на этот массив где-то.

Ответ 6

Использование PyQt5 и matplotlib версии 3.0.2

Если вы хотите добавить несколько кнопок, просто следуйте документу, заданному классом 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
# )

Так что вам нужно переопределить ваш класс, как было сказано ранее (вы также можете увидеть ниже, предопределенные кнопки, доступные в 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)