matplotlib and PyQt: Dynamic figure runs slow after several loads or looks messy

I have found a decent solution for the problem which will do until a better one is found.

The reason why the solution I tried caused a mess is that once an instance of GraphCanvas is created and set as a QCentralWidget, the QCentralWidget shrinks to the size of the GraphCanvas instance which is 500*400 in this case, and a Bbox of that size is saved. However, the figure itself uses the whole available space.

When you create a GraphCanvas and set is as the QCentralWidget, the widget uses the size of the GraphCanvas instance until the method it was created in (and all its parents) has finished executing. After that they both line up.

If we create the canvas in the __init__ method, it doesn’t cause a mess, because in the drawGraph method the size of QCentralWidget and GraphCanvas match and the right bbox size is used. However, when we create it in showButtonClick, the bbox will be in ‘wrong’ size until the method has finished.

In addition, if we create a QCentralWidget in the __init__ method of QMainWindow, the size of it will match the size of the whole window set by self.setGeometry(). After the method as finished, the size of QCentralWidget will be calculated to fit in the window and usually becomes smaller.

To solve this problem, I decided to create a dummy QWidget in the __init__ method and add that as QCentralWidget. Then in the showButtonClicked method I grab the width and height of the QCentralWidget and create a GraphCanvas using the saved width and height. That way the sizes match right from the beginning.

So here’s the relevant code:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setGeometry(100, 100, 640, 480)
        showButton = QPushButton('Show')

        toolbarShowButton = self.addToolBar('Show button toolbar')

        toolbarShowButton.addWidget(showButton)
        self.connect(showButton, SIGNAL('clicked()'), self.showButtonClicked)

        # dummy QWidget
        tempWidget = QWidget()
        self.setCentralWidget(tempWidget)

    def showButtonClicked(self):

        width = self.centralWidget().width()
        height = self.centralWidget().height()

        # convert to float (python 2) to prevent
        # flooring in the following divisions
        dpi = float(100)

        # create the canvas and replace the central widget
        self.graphLabel = GraphCanvas(self, width=width/dpi, height=height/dpi, dpi=dpi);
        self.setCentralWidget(self.graphLabel)

        self.graphLabel.drawGraph()

Leave a Comment