QVBoxLayout: How to vertically align widgets to the top instead of the center
Asked Answered
O

6

67

In Qt, When I add widgets to my layout, they are vertically centered by default. Is there a way to "List" the widgets from top to bottom instead of centering them vertically?

Ornas answered 10/4, 2012 at 2:16 Comment(0)
L
57

use void QLayout::setAlignment ( Qt::Alignment alignment ) method to set alignment according to your choice.

Lyra answered 10/4, 2012 at 4:31 Comment(1)
I don't think this gives enough information. For a start there is no such method: it is (in PyQt5) setAlignment(QWidget *w, Qt::Alignment alignment) and setAlignment(QLayout *l, Qt::Alignment alignment), and my first experiments seem to show that using either of these methods on a QVBoxLayout does not simply enable its added components to be aligned neatly to the top ...Saddlebow
O
61

If you have a QVBoxLayout and want your fixed size widgets to be stacked at the top, you can simply append a vertical stretch at the end:

layout.addStretch()

If you have multiple stretchers or other stretch items, you can specify an integer stretch factor argument that defines their size ratio.

See also addStretch and addSpacerItem.

Add two layout.addStretch() before and after adding the widgets to center them vertically:

    layout.addStretch()
    layout.addWidget(self.message)
    layout.addWidget(self.userid_field)
    layout.addWidget(self.password_field)
    layout.addWidget(self.loginButton)
    layout.addStretch()

Not sure whether this answers your original question, but it is the answer to the one that I had when googling and being led to this page - so it might be useful for others too.

Overview answered 12/6, 2017 at 13:16 Comment(3)
I used to be a fan of this method, but I just realized that layout.setAlignment(Qt::AlignTop) provides a better behavior than layout.addStretch() when a top-aligned layout has top-aligned child layouts. Using addStretch(), the available space will be equally distributed between parent and child spacers: [[h1--][h2--]--]. Using setAlignment(), the space is given in priority to the parent: [[h1][h2]------], keeping the height of the children to their preferred height h1 and h2. I think the latter is often a more desired behavior, although the former may definitely have use cases.Floatation
@BorisDalstein Strange... my experience is if anything the opposite to what you describe.Saddlebow
In the QtCreator, this is called Vertical Spacer (or Horizontal Spacer), and their icons are a spring, if someone is trying to do this in the graphical interface.Perceptual
L
57

use void QLayout::setAlignment ( Qt::Alignment alignment ) method to set alignment according to your choice.

Lyra answered 10/4, 2012 at 4:31 Comment(1)
I don't think this gives enough information. For a start there is no such method: it is (in PyQt5) setAlignment(QWidget *w, Qt::Alignment alignment) and setAlignment(QLayout *l, Qt::Alignment alignment), and my first experiments seem to show that using either of these methods on a QVBoxLayout does not simply enable its added components to be aligned neatly to the top ...Saddlebow
P
33

I find this a little more complicated than just using layout.setAlignment(). It kept not working for me until just now, when I figured out that if you have expanding widgets that you set a maximum height for, then that widget will not be aligned the way you want.

Here is example code that does not top align the QTextBrowser() widget even though I call layout.setAlignment(Qt.AlignTop). Sorry that it is in Python, but it is pretty easy to translate to C++ (I have gone the other way many times).

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWidget(QWidget):
    """
    Create a widget that aligns its contents to the top.
    """
    
    def __init__(self, parent=None):
        
        QWidget.__init__(self, parent)
        
        layout = QVBoxLayout()
        
        label = QLabel('label:')
        layout.addWidget(label)

        info = QTextBrowser(self)
        info.setMinimumHeight(100)
        info.setMaximumHeight(200)
        layout.addWidget(info)        
        # Uncomment the next line to get this to align top.
#         layout.setAlignment(info, Qt.AlignTop)
        
        # Create a progress bar layout.
        button = QPushButton('Button 1')        
        layout.addWidget(button)        

        # This will align all the widgets to the top except
        # for the QTextBrowser() since it has a maximum size set.
        layout.setAlignment(Qt.AlignTop)
        
        self.setLayout(layout)


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)

    widget = MyWidget()
    widget.show()
    widget.resize(QSize(900, 400))
    
    app.exec_()

The following explicitly calls layout.setAlignment(info, Qt.AlignTop) to get the expanding text widget to work.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWidget(QWidget):
    """
    Create a widget that aligns its contents to the top.
    """
    
    def __init__(self, parent=None):
        
        QWidget.__init__(self, parent)
        
        layout = QVBoxLayout()
        
        label = QLabel('label:')
        layout.addWidget(label)

        info = QTextBrowser(self)
        info.setMinimumHeight(100)
        info.setMaximumHeight(200)
        layout.addWidget(info)        
        # Uncomment the next line to get this to align top.
        layout.setAlignment(info, Qt.AlignTop)
        
        # Create a progress bar layout.
        button = QPushButton('Button 1')        
        layout.addWidget(button)        

        # This will align all the widgets to the top except
        # for the QTextBrowser() since it has a maximum size set.
        layout.setAlignment(Qt.AlignTop)
        
        self.setLayout(layout)


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)

    widget = MyWidget()
    widget.show()
    widget.resize(QSize(900, 400))
    
    app.exec_()
Peephole answered 15/2, 2013 at 17:21 Comment(1)
In PyQt6, AlignTop will be found under Qt.AlignmentFlag.AlignTop: layout.setAlignment(Qt.AlignTop) should be layout.setAlignment(Qt.AlignmentFlag.AlignTop)Skipp
F
10

After comparison between the two solutions, it seems that :

myLayout.setAlignment(Qt::AlignTop)

works for several widget alignement but :

myLayout.setAlignment(myWidget, Qt::AlignTop)

works only for the first widget you add to the layout. After all, the solution depends also to the QSizePolicy of yours widgets.

Friary answered 16/4, 2014 at 14:7 Comment(0)
H
3

If you are using QT creator, you just add a "Vertical Spacers" at the bottom of your widget.

Housewares answered 18/1, 2021 at 4:56 Comment(0)
O
0

In pyQt (and PySide) we have Qt.AlignCenter (align on main direction), Qt.AlignHCenter (align on horizontal direction), Qt.AlignVCenter (align on vertical direction), use one of it when you need it.

Obscuration answered 10/6, 2022 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.