pythonmatplotlibpyqt5qtoolbar

How do I make the matplotlib toolbar able to dock to the side in a pyqt5 window?


I have embedded a matplotlib figure in a pyqt5 window along with the toolbar, this is my code:

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


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

        self.figure = Figure(tight_layout=True)
        self.canvas = FigureCanvas(self.figure)
        self.setCentralWidget(self.canvas)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.addToolBar(self.toolbar)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)

    mw = PlotWindow()
    ax = mw.figure.add_subplot()
    mw.show()

    exit(app.exec_())

And this is what it looks like:

enter image description here

I can drag the toolbar to the bottom and dock it there:

enter image description here

But I can't dock it to the side (left or right).

This is something you can do with any other standard pyqt5 toolbar, why does it not work with the matplotlib toolbar? and how do I make it work?

I can do it in code by changing this line:

# self.addToolBar(self.toolbar)
self.addToolBar(QtCore.Qt.LeftToolBarArea, self.toolbar)

The result is:

enter image description here

Which is what I'm after, but if I then undock the toolbar from the left side I can no longer dock it there again and can only dock it in top and at the bottom.


Solution

  • The QToolBar provided by matplotlib is configured to only allow dragging on the top and information as seen in the source code:

    self.setAllowedAreas(QtCore.Qt.ToolBarArea(
        _to_int(_enum("QtCore.Qt.ToolBarArea").TopToolBarArea) |
        _to_int(_enum("QtCore.Qt.ToolBarArea").BottomToolBarArea)))
    

    The solution is to establish all areas:

    self.toolbar.setAllowedAreas(QtCore.Qt.ToolBarArea.AllToolBarAreas)