Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to get the height of QVBoxLayout ?



  • How to get the height of QVBoxLayout ?

    titles = QVBoxLayout()
    titles.addLayout(QLabel('Title'))
    titles.addWidget(QLabel('SubTitle'))
    
    print(titles.contentsRect())  # =>  PySide2.QtCore.QRect(0, 0, 0, 0)
    

    Pyside2 5.13.1 on Manjaro


  • Lifetime Qt Champion

    @NonNT Why do you need the height of a layout? Usually one is interested in size of a widget.



  • @NonNT
    Apart from what @jsulm has just said.

    I would assume the reason for QRect(0, 0, 0, 0) is that if the code is as you show the QVBoxLayout, and its widgets, are in limbo-land size-/layout-wise until you actually put them onto a window or actually show it? At minimum try putting the layout somewhere, and possibly have to wait till it's actually shown, not sure about that?


  • Moderators

    @NonNT

    I don't know how the python bindings handle this, but this:

    titles.addLayout(QLabel('Title'))
    

    should actually not be possible

    besides that, @JonB is right, until shown, the content hight/width should be 0



  • @J-Hilk
    Good spot, I didn't actually notice that! You can add a QLayout to a QLayout, but you can't pass a QWidget to addlayout()!

    I don't know how the python bindings handle this

    I tried in PyQt5, and get run-time error:

    TypeError: addLayout(self, QLayout, stretch: int = 0): argument 1 has unexpected type 'QLabel'

    PySide2 run-time error:

    TypeError: 'PySide2.QtWidgets.QBoxLayout.addLayout' called with wrong argument types:
    PySide2.QtWidgets.QBoxLayout.addLayout(QLabel)
    Supported signatures:
    PySide2.QtWidgets.QBoxLayout.addLayout(PySide2.QtWidgets.QLayout, int = 0)

    Don't you just love it when Python has to run-time error where a decent language would pick it up at compile time :(


  • Moderators

    @JonB lovely
    do also not get a hint where in your files this happened?



  • @J-Hilk
    Yes, they both gave me a stacktrace/code lines. Didn't paste, but I didn't mean to imply they did not produce those. Just that you only discover when/if you hit the code at run-time, where code above would not compile in C++. Since I have to use Python for my Qt work, I like to moan about it a lot ;)



  • @J-Hilk Sorry, yes, it should be addWidget

    logo = QSvgWidget()
    logo.load('logo.svg')
    
    titles = QVBoxLayout()
    titles.addWidget(QLabel('Title'))
    titles.addWidget(QLabel('SubTitle'))
    
    titleBox = QHBoxLayout()
    titleBox.addWidget(logo)
    titleBox.addLayout(titles)
    

    logo should have the same width as height, depending on the height of titles
    but now the width of logo is dynamic, but should be fixed.
    for logo.setFixedSize() I need the height of titles

    thanks


  • Moderators

    @NonNT
    for such cases, QWidgets have a int QWidget::heightForWidth(int w) const but you have to override that function for it to work as indented. I'm not sure how to do this with python ..


    Here's an example on how to do such a thing in c++, still working in Qt5.12 +
    https://stackoverflow.com/a/18923122



  • @NonNT said in How to get the height of QVBoxLayout ?:

    for logo.setFixedSize() I need the height of titles

    As @J-Hilk has said, QWidget::heightForWidth() looks like the best way to go. (I don't know if https://doc.qt.io/qt-5/qsizepolicy.html#setHeightForWidth does it for you without override.) But if you are still asking to get the size of the layout, I don't see you have acted on what we said earlier?



  • Don't know how to override QWidget::heightForWidth(int w)

    But I can sum up the heights of the widgets and the spacing between the widgets.

    title = QLabel(f'<h3>{self.title}</h3>')
    subTitle = QLabel(self.subTitle)
    
    widgetTmp = QWidget()
    vboxlayoutTmp = QVBoxLayout(widgetTmp)
    vboxlayoutHeight = title.sizeHint().height() + vboxlayoutTmp.layout().spacing() + subTitle.sizeHint().height()
    
    logo = QSvgWidget()
    logo.load('logo.svg')
    logo.setFixedSize(vboxlayoutHeight, vboxlayoutHeight)
    
    labels = QVBoxLayout()
    labels.addWidget(title)
    labels.addWidget(subTitle)
    
    titleBox = QHBoxLayout()
    titleBox.addWidget(logo)
    titleBox.addLayout(labels)
    

  • Banned

    Okay I have if I am understanding this correctly self.logo is a square object and you want it to be the same height as that taken up by the self.lblTitle and self.lblSubTitle which are both contained within vbxTitles layout

    Okay if done correctly this should actually be handled by the QLayout objects because a QLayout's objects unless told to do otherwise generally attempt to fill all the allowable space given to them based on the overall size of the boxes they are contained within apply any restrictions associated with that specific object (i.e. buttons have a fixed height but no fixed width)

    I have done this with things like chessboard renditions as well as other similar objects where one object is dependent upon its associated object for its dynamic size and once I figured out the setup for that particular layout it works just fine. I suggest digging a bit deeper into what you are attempting to do and how the dynamic nature of layouts is implemented


Log in to reply