Ilyes Ferchiou
Ilyes Ferchiou

Reputation: 583

QWidget Geometry() not updating

I have QWidgets lined up in a QVBoxLayout inside a QScrollArea with setWidgetResizable(True)

When I resize one of the QWidgets, the QWidgets relocate themselves accordingly in the graphical user interface, but their geometry() property doesn't reflect that, geometry().x() and geometry().y() both remain the same before and after relocation.

The only method I have found so far to update the x() and y() coordinates is to hide() and show() the QScrollArea.

I have tried update(), updateGeometry() and repaint() without any success.

Here is a sample test code that I made to summarize the problem :

import sys
from PySide import QtGui, QtCore


class MainWindow(QtGui.QMainWindow):

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

        self.showMaximized()
        self.widget_window = QtGui.QWidget()
        self.scrollarea = QtGui.QScrollArea()
        self.v_layout = QtGui.QVBoxLayout()
        self.test_1 = QtGui.QPushButton('Test 1')
        self.test_2 = QtGui.QPushButton('Test 2')
        self.v_layout.addWidget(self.test_1)
        self.v_layout.addWidget(self.test_2)
        self.widget_window.setLayout(self.v_layout)
        self.scrollarea.setWidgetResizable(True)
        self.scrollarea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollarea.setAlignment(QtCore.Qt.AlignCenter)
        self.scrollarea.setWidget(self.widget_window)
        self.setCentralWidget(self.scrollarea)
        print(self.test_2.geometry().x())
        print(self.test_2.geometry().y())
        self.test_1.setFixedHeight(1000)
        #uncommenting the following next two lines, solves the problem
        #self.scrollarea.hide()
        #self.scrollarea.show()
        print(self.test_2.geometry().x())
        print(self.test_2.geometry().y())

def main():
    app = QtGui.QApplication(sys.argv)
    main = MainWindow()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

My questions are :

  1. Is there a better solution ?
  2. Isn't updateGeometry() supposed to actually update the geometry() ?
  3. Why is this behavior happening ? (i.e why does it update graphically but not programmatically ?)
  4. Can using hide() and show() successively cause some problems in other contexts (window flickering or something else...) ?

Upvotes: 2

Views: 3751

Answers (1)

Avaris
Avaris

Reputation: 36715

When you update the GUI, it's not instantaneous. It's performed when you give the control to the event loop. In this case, it's done after __init__ completes, which is obviously after all your prints. Therefore, you'll see the old position.

hide/show forces an update at that point. That's why you get correct values. However, this is not the best way, because you might observe flicker while hide/show does its job.

Better way would be telling the event loop to process events before continuing. This will ensure that the GUI is updated:

    #...
    print(self.test_2.geometry().x())
    print(self.test_2.geometry().y())
    self.test_1.setFixedHeight(1000)
    QtGui.QApplication.processEvents()
    print(self.test_2.geometry().x())
    print(self.test_2.geometry().y())
    #...

PS: I'm assuming, you have good reasons to do this. Most of the time, you won't care when the GUI is updated.

Upvotes: 2

Related Questions