3

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.

Community
  • 1
  • 1
goryef
  • 1,337
  • 3
  • 22
  • 37
  • provide a [mcve] – eyllanesc Jul 22 '18 at 14:25
  • Qt cannot know the true size before the frame is rendered by the window-manager. – ekhumoro Jul 22 '18 at 15:35
  • I am trying to place widget in a center of the QFrame. is there a way to do without knowing a true size? – goryef Jul 22 '18 at 15:44
  • @goryef What widget do you want to place in the center of the QFrame? – eyllanesc Jul 23 '18 at 02:14
  • @goryef where do you use `wndw_width`? – eyllanesc Jul 23 '18 at 02:15
  • @eyllanesc I would like to be able to have a full control over the size and placement of the widgets. I am aware of the layouts but want to be able to place widgets anywhere I want. The wind_width in the code is just to show that QFrame width returns value much smaller that visually appears. As per answer above that’s b:c I query it before it’s rendered. I was just wondering if there any “tricks” to work around it. I am very new to Python. All my experience is with Vb.net. – goryef Jul 24 '18 at 03:01
  • @goryef In Qt the sizes only apply when the widget is visible, and the constructor is called when it is not yet visible, if you ask for a specific case it could show you a practical example. – eyllanesc Jul 24 '18 at 03:03
  • @goryef I see that you never use wndw_width so that's why it's my question – eyllanesc Jul 24 '18 at 03:04
  • @goryef Why do you say that the width of the Frame should be 1440? – eyllanesc Jul 24 '18 at 03:21
  • @eyllanesc I expect that width of the frame should be way over 640px. i updated original post with code and image sample – goryef Jul 24 '18 at 11:48
  • @eyllanesc. I update original post with the example – goryef Jul 24 '18 at 13:16

1 Answers1

6

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

eyllanesc
  • 235,170
  • 19
  • 170
  • 241