3

I have a PyQt window that needs to have both a plot and navigation toolbar. However, I can't seem to get the two objects to mesh together; i.e., with the toolbar on top of the plot, expanding the same horizontal length, scaling appropriately, and not overlapping. Below is my minimum, working example. thank you so much for taking a look!

import sys, os

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import random

class App(QtGui.QMainWindow):

    def __init__(self):
        super(App, self).__init__()
        self.left = 10
        self.top = 10
        self.title = 'Minimum, working example'
        self.width = 640
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        m = PlotCanvas(self, width=5, height=4)
        m.move(0,0)
        self.show()


class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.updateGeometry(self)

        ##########################
        #trouble seems to be here:
        fig.set_tight_layout(True)
        self.canvas = FigureCanvas(fig)
        self.toolbar = NavigationToolbar(self.canvas, self)
        ##########################

        self.plot()


    def plot(self):
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-')
        ax.set_title("Is this getting overlapped by the toolbar?")
        self.draw()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

1 Answer 1

3

When you use self.canvas = FigureCanvas (fig) you are creating another FigureCanvas, why create another ?, it is not necessary.

Why are they overlapping?

The position of a child widget is relative to the parent, in this case it is self.toolbar is the children of self.canvas so the self.toolbar will be within the self.canvas.

In order to handle the position and size of the widgets, Qt offers the layouts, and in this case it is necessary. On the other hand, there is no need for the toolbar to be inside the PlotCanvas class. And finally when using QMainWindow you should not place the widgets directly since it has a custom layout so you must create a centralwidget.

import sys, os

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import random

class App(QtGui.QMainWindow):
    def __init__(self):
        super(App, self).__init__()
        self.left = 10
        self.top = 10
        self.title = 'Minimum, working example'
        self.width = 640
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        centralwidget = QtGui.QWidget()
        self.setCentralWidget(centralwidget)
        m = PlotCanvas(self, width=5, height=4)
        toolbar =  NavigationToolbar(m, self)
        vbl = QtGui.QVBoxLayout(centralwidget)
        vbl.addWidget(toolbar)
        vbl.addWidget(m)
        self.show()


class PlotCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        self.updateGeometry()
        fig.set_tight_layout(True)
        self.plot()

    def plot(self):
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-')
        ax.set_title("Is this getting overlapped by the toolbar?")
        self.draw()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Amazing, so helpful! Thank you so much, eyllanesc!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.