Search code examples
pythonmatplotlibplotpyqt5

How to detect pan and zoom action in matplotlib navibar?


I am using the matplotlib canvas and navbar by creating a custom MplWidget in python, as follows:

from PyQt5.QtWidgets import QWidget, QVBoxLayout
from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as
        FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure


class MplWidget(QWidget):

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.canvas = FigureCanvas(Figure())
        vertical_layout = QVBoxLayout()
        vertical_layout.addWidget(self.canvas)

        self.canvas.axes = self.canvas.figure.add_subplot(111)
        self.setLayout(vertical_layout)
        self.canvas.toolbar = NavigationToolbar(self.canvas, self)
        self.layout().addWidget(self.canvas.toolbar)
        self.layout().addWidget(self.canvas)
        self.canvas.axes.grid(b=True, which='both', axis='both')
        self.canvas.figure.set_tight_layout(True)

I want to detect when the pan or the zoom tool is toggled. I found this: in matplotlib how do I catch that event "zoom tool" has been selected? Following the solution there, I tried

self.canvas.toolbar.get_state()['_current_action']

or simply just self.canvas.toolbar.get_state(), but I get the error:

AttributeError: 'NavigationToolbar2QT' object has no attribute 'get_state'

It seems like a very basic function to see which action is in use currently, so I am sure there is a simple solution, but I can't seem to find it.

zoom toggled


Solution

  • I've found two solutions, but I don't know if they work with all kinds of backends (not an expert in those).


    The first is axes-dependant:

    ax.get_navigate_mode()
    

    it returns 'PAN', 'ZOOM', or None.

    (Link to documentation)


    The second is figure-dependant:

    fig.canvas.toolbar.mode
    

    it returns "pan/zoom", "zoom rect" or "".

    (Link to source code of the NavigationToolbar2 object)