How can I add custom toggle tool to matplotlib toolbar inPyQt5 application?

Viewed 345

I'm making a PyQt5 application with embedded matplotlib canvas. I need to add custom tools to Matplotlib toolbar that can be toggled in the same way as Matplotlib's default tools "zoom" and "pan". Problem is that Matplotlib's NavigationToolbar2QT-class doesn't seem to have functions to directly add tools unlike ToolbarQt, which I can't get working.

Here is a simplified version of my trial code using NavigationToolbar2QT:

import sys

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

ui_file = 'user_interface.ui'


class ToolBar(NavigationToolbar):
    def __init__(self, figure_canvas, parent=None):
        NavigationToolbar.__init__(self, figure_canvas, parent=None)
        # Add custom tools here


class MplWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.canvas = FigureCanvas(Figure())
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)
        self.canvas.figure.add_subplot(111)
        self.canvas.draw()


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi(ui_file, self)
        self.toolbar = ToolBar(self.MplWidget.canvas)
        self.ToolBarLayout.addWidget(self.toolbar)
        self.show()


app = QtWidgets.QApplication(sys.argv)
window = Ui()
sys.exit(app.exec_())

I know I can add new tools to my custom ToolBar-class by adding it to NavigationToolbar2QT's toolitems, but I can't implement the toggle functionality by doing this.

I also tried to do this with ToolbarQt:

import sys

from PyQt5 import QtWidgets, uic
from matplotlib.backends.backend_qt5 import ToolbarQt
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.backend_managers import ToolManager
from matplotlib import backend_tools
from matplotlib.figure import Figure
from matplotlib import pyplot
import matplotlib
pyplot.rcParams['toolbar'] = 'toolmanager'
matplotlib.use('Qt5Agg')

ui_file = 'user_interface.ui'


class MplWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.canvas = FigureCanvas(Figure())
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)
        self.canvas.figure.add_subplot(111)
        self.canvas.draw()


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi(ui_file, self)
        self.tool_manager = ToolManager(self.MplWidget.canvas.figure)
        backend_tools.add_tools_to_manager(self.tool_manager)
        self.toolbar = ToolbarQt(self.tool_manager, self)
        backend_tools.add_tools_to_container(self.toolbar)
        self.ToolBarLayout.addWidget(self.toolbar)
        # Add custom tool here
        self.show()


app = QtWidgets.QApplication(sys.argv)
window = Ui()
sys.exit(app.exec_())

In this case, however, even the default tools will cause the following error even though Qt5-backend is used.

AttributeError: 'FigureCanvasQTAgg' object has no attribute '_tkcanvas'
0 Answers
Related