pythonpyqtpyqt5qframe

PyQt5 actual size of a QFrame


Is there a way to get an actual size of the QFrame in PyQt5? My monitor resolution is 1920x1080. After I add QFrame to layout it fills the whole window in my case about 1200px. However the width() command returns 640. It seems that default size 640x480 and it doesn't change for querying?

I want to be able to center widget without use of layouts b/c i am planning to use several overlays in my design.

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import PyQt5.QtWidgets
import sys

class MainWindow(QMainWindow):

   def __init__(self, parent):

    QMainWindow.__init__(self, parent)
    self.setWindowTitle('Sample')
    size_object = PyQt5.QtWidgets.QDesktopWidget ().screenGeometry ( -1 )  # active screen
    scr_width = size_object.width ()
    scr_height = size_object.height()
    self.resize ( 3 / 4 * scr_width, 3 / 4 * scr_height )

    qr = self.frameGeometry()  # geometry of the main window
    cp = QDesktopWidget().availableGeometry().center()  # center point of screen
    qr.moveCenter(cp)  # move rectangle's center point to screen's center point
    self.move(qr.topLeft())  # top left of rectangle becomes top left of window centering it

    self.setCentralWidget ( QWidget ( self ) )
    self.hbox = QHBoxLayout ()
    self.centralWidget ().setLayout ( self.hbox )

    self.frame_sample = QFrame ()
    self.hbox.addWidget ( self.frame_sample )
    self.frame_sample.setStyleSheet ( "background-color: rgb(200, 100, 255)" )


    button_go = QPushButton ("sample",  self.frame_sample )
    button_go.setStyleSheet (
        'QPushButton {background: red; yellow; font-weight: bold;'
        ' text-decoration: underline; text-align: middle;}' )
    button_go.resize ( 100, 100 )
    button_go.move ( (self.frame_sample.width () - button_go.width ()) / 2,
                     (self.frame_sample.height () - button_go.height ()) / 2 )


app = QApplication ( sys.argv )
myWindow = MainWindow ( None )
myWindow.show ()
app.exec_ ()

enter image description here

I want a button to appear in the middle of the QFrame based on calculated position.


Solution

  • The geometry is not updated immediately since it involves a cost, Qt is done when the widget is visible or needs to be updated, in your case the calculation must be done when it is shown or when the widget is resized.

    import sys
    
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    
    
    class MainWindow(QMainWindow):
        def __init__(self, parent=None):
            QMainWindow.__init__(self, parent)
            self.setWindowTitle('Sample')
            size_object = QDesktopWidget().screenGeometry(-1)  # active screen
            scr_width = size_object.width ()
            scr_height = size_object.height()
            self.resize ( 3 / 4 * scr_width, 3 / 4 * scr_height )
    
            qr = self.frameGeometry()  # geometry of the main window
            cp = QDesktopWidget().availableGeometry().center()  # center point of screen
            qr.moveCenter(cp)  # move rectangle's center point to screen's center point
            self.move(qr.topLeft())  # top left of rectangle becomes top left of window centering it
    
            self.setCentralWidget(QWidget())
            self.hbox = QHBoxLayout(self.centralWidget())
    
            self.frame_sample = QFrame()
            self.hbox.addWidget(self.frame_sample )
            self.frame_sample.setStyleSheet( "background-color: rgb(200, 100, 255)" )
    
    
            self.button_go = QPushButton("sample",  self.frame_sample)
            self.button_go.setStyleSheet(
                'QPushButton {background: red; yellow; font-weight: bold;'
                ' text-decoration: underline; text-align: middle;}' )
            self.button_go.resize (100, 100)
    
        def event(self, e):
            if e.type() in (QEvent.Show, QEvent.Resize):
                geo = self.button_go.geometry()
                geo.moveCenter(self.frame_sample.rect().center())
                self.button_go.setGeometry(geo)
    
            return QMainWindow.event(self, e)
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        myWindow = MainWindow()
        myWindow.show ()
        sys.exit(app.exec_())
    

    enter image description here