1

I am not able to find a working code example for the various NavigationToolbar2 callbacks. I have read through the docs, but am still working my way up the learning curve and am not having any luck locating code examples showing how to properly connect to the events I'm interested in.

For specificity, let's focus only on "How do I attach code to release_zoom()?"

The above link provides this documentation:

release_pan(event) - Callback for mouse button release in pan/zoom mode.

Lines of interest in the (incorrectly) working example below are:

self.nt.release_zoom('button_release_event')
self.canvas.mpl_connect('button_release_event', self.on_rel_zoom1)
self.canvas.mpl_connect('release_zoom', self.on_rel_zoom2)

I only manage to connect to the button_release_event. How do I correctly connect to release_zoom()?

from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import numpy as np


class PlotWin(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(PlotWin, self).__init__(parent)
        QtWidgets.QMainWindow.__init__(self, parent)

        self.win = QtWidgets.QWidget(self)
        self.setCentralWidget(self.win)
        layout = QtWidgets.QVBoxLayout(self.win)

        self.canvas = FigureCanvas(Figure())
        layout.addWidget(self.canvas)
        self.nt = NavigationToolbar(self.canvas, self)
        layout.addWidget(self.nt)
        self.ax1 = self.canvas.figure.add_subplot(111)
        self.ax1.plot(np.linspace(1, 100, 100), np.random.rand(100, 1))

        self.nt.release_zoom('button_release_event')
        self.canvas.mpl_connect('button_release_event', self.on_rel_zoom1)
        self.canvas.mpl_connect('release_zoom', self.on_rel_zoom2)

    def on_rel_zoom1(self, event):
        print('One')

    def on_rel_zoom2(self, event):
        print('Two')


if __name__ == '__main__':
    import sys

    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    window = PlotWin()
    window.show()
    app.exec_()
dondsmith2
  • 23
  • 6

1 Answers1

2

release_pan or release_zoom are callbacks. Those are the functions which are called once the conditions of the user releasing the mouse in pan or zoom mode are satisfied. You cannot connect them, but you may connect to them and of course you may call them if needed.

The possible events to connect are listed in the documentation. They are

events = ['resize_event', 
          'draw_event', 
          'key_press_event', 
          'key_release_event', 
          'button_press_event', 
          'button_release_event', 
          'scroll_event', 
          'motion_notify_event', 
          'pick_event', 
          'idle_event', 
          'figure_enter_event', 
          'figure_leave_event', 
          'axes_enter_event', 
          'axes_leave_event', 
          'close_event']

Since there is no such thing as a "release_zoom_event", this can also not be connected.

But.. you may create this "release_zoom_event" yourself, if needed. This is essentially described in matplotlib hooking in to home/back/forward button events for the "home" button. Adapting that example to the "release_zoom_event" would look like this:

import matplotlib.pyplot as plt
from matplotlib.backend_bases import NavigationToolbar2

release_zoom = NavigationToolbar2.release_zoom

def new_release_zoom(self, *args, **kwargs):
    s = 'release_zoom_event'
    self.canvas.callbacks.process(s, args[0])
    release_zoom(self, *args, **kwargs)

NavigationToolbar2.release_zoom = new_release_zoom

def handle_release_zoom(evt):
    print('release_zoom_event')
    print(evt.xdata,evt.ydata)

fig = plt.figure()
fig.canvas.mpl_connect('release_zoom_event', handle_release_zoom)
plt.plot([1,3,1])
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Agreed - ' connect to': My wording was imprecise. Can you please provide a simple 1- or 2-line example of exactly *how* it is that I connect to them? – dondsmith2 Mar 01 '18 at 21:33
  • "Connect" or "connect to" is a bit tricky, and I'm not even 100% sure if the wording is now correct in my answer, but in any case the main point is that there is no such thing as `release_pan_event`; but you may create it if you wish; this is of course longer than 2 lines, as you need to monkey patch the source. I updated the answer accordingly. – ImportanceOfBeingErnest Mar 01 '18 at 22:31
  • Perfect, thanks again! I think some version of this example should be readily available somewhere in the documentation...for the life of me I could not locate a way to figure this out. – dondsmith2 Mar 01 '18 at 23:09
  • I'm not sure if providing examples of monkey patching the library would make sense in a documentation. The docs are clear about the existing events. If you want another event, it's your own responsibility to obtain it somehow. – ImportanceOfBeingErnest Mar 01 '18 at 23:42
  • Better description of events is given here: https://matplotlib.org/users/event_handling.html#event-connections – bzu Apr 17 '19 at 16:20