3. Qt Widgets Layouts
When you create a Qt widget like QPushButton you need a way to position it inside a window or a container widget. It is possible, but quite uncommon, to position Qt widgets by setting their x and y coordinates - Most Qt applications use layouts to automatically arrange widgets in rows, columns grids, forms, or stacks, to achieve the desired layout1.
3.1 Laying out Widgets Vertically - QVBoxLayout
QVBoxLayout arranges widgets in a column. If you look up the QVBoxLyout parents in the Qt documentation, you’ll notice that QWidget is not a QVBoxLayout’s parent class. This means you cannot show a layout on the screen - it is not a visual element but a geometry manager.
![]() |
To add a vertical layout to a |
Create a
QVBoxLayoutinstance and set it as your window layout withsetLayout(). This also works for anyQWidgetsubclass. You can nest layouts inside other layouts to achieve complex layouts.Create widgets you want to lay out. Here we create three
QPushButtoninstances.Add them to the layout using
addWidget(). For nested layouts you would useaddLayout()instead.
Run the script and resize the window: The buttons stack vertically and expand horizontally to fill the width, but their height stays fixed, creating gaps between them. There are two ways you can change this:
- Add stretchable space with
addStretch()at the end of the layout - it pushes the widgets to the top while allowing empty space to grow. - Set a widget’s size
Expandingfor both directions, e.g.button_1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding). This lets it resize in both axes.
We’ve also connected all three buttons’ clicked signals to a single @Slot() method. Inside the slot, you can use QObject.sender() to identify the sender:
sender = self.sender()
as we need a way to tell which button emitted the clicked signal. This lets us reuse a single slot to handle signals from different widgets - but keep in mind this warning from the Qt docs:
Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.
When executed, the script shows a window like this:

3.2 Horizontal Layout - QHBoxLayout
![]() |
|
Create the layout and assign it to a
QWidgetwithsetLayout()Create child widgets. Here, a
QPushButtonandQLabel. We set the label’s minimum width to fit its text.Add them to the layout using
addWidget()in the desired order.
For interactivity, we’ve connected the button’s clicked signal to update the label with the current time using QTime.currentTime(). This shows an important point: Qt is more than a GUI toolkit and offers tools that overlap with Python’s - for instance the developer needs to decide whether to use time from the Python standard library or QTime from PySide6,QtCore.
After execution, you’ll see a window like this:

Both layout classes arrange widgets in the order you add them with addWidget(), QVBoxLayout top to bottom, and QHBoxLayout left to right. You can change this their setDirection() method with the QBoxLayout.BottomToTop or QBoxLayout.RightToLeft. You can achieve dynamic layouts by using removeWidget() to remove a widget from a layout or insertWidget() to insert a widget out of order.
If you create a widget without setting its parent, as we do in the above examples, adding them to a widget’s layout reparents them to that widget.
3.3 Grid Layout - QGridLayout
QGridLayout positions widgets in a grid. Unlike linear layouts, you specify each widget’s row and column when adding it.
![]() |
To use a grid layout: |
Create a
QGridLayoutinstance and set it as aQWidgetlayout.Create widgets and add them with
addWidget(widget, row, col).Leave cells empty for gaps. For spanning, useaddWidget(widget, row, col, row_span, col_span)- e.g.,addWidget(self.label, 4, 0, 1, 4)for a label spanning one row over four columns.
Here, we populate a 4x4 grid with 16 QPushButtons using two nested loops. Using sender() in the slot lets us identify the clicked button.
After execution, the window looks like this:

3.4 Form Layout - QFormLayout
QFormLayout creates a two-column form layout: labels on the left, fields on the right, similar to HTML forms.
![]() |
To implement it: |
Create a
QFormLayoutinstance and set it as theQWidgetlayout.Create child widgets. Since we need to access the widgets from the slot method, we make the them
Windows instance members.Add child widgets to the form using
QFormLayout.addRow(label_text, widget).addRow()is a convenience method that automatically creates aQLabelinstance for you, setting its text tolabel_text.
In this example, three QlineEdit fields handle user input. Their editingFinished is emitted on pressing Enter/Return or when focus leaves the changed field. A single slot updates a summary QLabel with the values. (No sender() needed here since we reference widgets directly.)

