Olaf
Olaf

Reputation: 29

QGraphicsView.fitInView() not working as expected

Why would the QGraphicsView.fitInView() work only after I resize the window?

I am using Python 2.7.7 and Qt 4.8.7 on MS Windows 10. Below is the code to demonstrate the problem.

Thank you for sharing your insights and help. Olaf

import sys

from PyQt4 import QtCore
from PyQt4 import QtGui


class Test(QtGui.QWidget):
    def __init__(self, *args):
        super(Test, self).__init__(*args)

        self.setObjectName("Form")
        self.resize(200, 100)
        self.gridLayout = QtGui.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.graphicsView = QtGui.QGraphicsView(self)
        self.graphicsView.setObjectName("graphicsView")
        self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1)

        deltaX = 40
        deltaY = 40
        width = 200 - deltaX
        height = 200 - deltaY

        print 'constructor start'
        scene = QtGui.QGraphicsScene(self)
        for i in range(5):
            scene.addLine(0, i*deltaY, width, i*deltaY)
            scene.addLine(i*deltaX, 0, i*deltaX, height)
        self.graphicsView.setScene(scene)
        self.graphicsView.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
        print 'constructor end'

    def resizeEvent(self, event):
        print 'resize event start'
        scene = self.graphicsView.scene()
        r = scene.sceneRect()
        print '  rect %d %d %d %d' % (r.x(), r.y(), r.width(), r.height())
        self.graphicsView.fitInView(r, QtCore.Qt.KeepAspectRatio)
        print 'resize event end'

if __name__ == '__main__':
    a = QtGui.QApplication(sys.argv)
    w = Test()
    a.setActiveWindow(w)
    w.show()
    a.exec_()

Upvotes: 2

Views: 2937

Answers (1)

musicamante
musicamante

Reputation: 48529

When a widget is first initialized, it (usually, but that depends on a lot of things) receives a resizeEvent before being actually shown.

The solution is to implement the resize also when the showEvent is called (which happens everytime the widget or its top level parent is shown by calling show() or setVisible(True):

    def updateView(self):
        scene = self.graphicsView.scene()
        r = scene.sceneRect()
        print '  rect %d %d %d %d' % (r.x(), r.y(), r.width(), r.height())
        self.graphicsView.fitInView(r, QtCore.Qt.KeepAspectRatio)

    def resizeEvent(self, event):
        print 'resize event start'
        self.updateView()
        print 'resize event end'

    def showEvent(self, event):
        # ensure that the update only happens when showing the window
        # programmatically, otherwise it also happen when unminimizing the
        # window or changing virtual desktop
        if not event.spontaneous():
            print 'show event'
            self.updateView()

Upvotes: 6

Related Questions