PyQt’s layout manager, Layout Managers, provides a user-friendly and efficient way to arrange graphical components or widgets on a GUI. Placing widgets correctly will make your GUI application look more polished and professional. Learning to do this effectively is an essential skill for developing and running GUI applications using Python and PyQt.

In this tutorial, you will learn:

  • The use of PyQtlayout managersWhat are the benefits?
  • How to use PyQtlayout managersLay out widgets programmatically on the GUI
  • How do I choose the right one for your GUI applicationlayout manager
  • How do I lay out widgets in my main-based and dialog-based applications

With this knowledge and skills, you can create professional-looking GUI applications using Python and PyQt.

Lay out graphical elements on the GUI

When creating graphical user interface (GUI) applications, a common problem is getting graphical components (buttons, menus, toolbars, labels, and so on) to be placed consistently on forms and Windows. This process is called GUI Layout, and it is an important step in creating GUI applications.

Previously, if you wanted to place graphical components or widgets on a window, you could have done one of the following:

  • Determine and manually set the static size and position for each widget on the window.
  • Calculates and sets the size and position of each widget dynamically.

The first approach is fairly straightforward, but has at least the following disadvantages:

  • Your Windows will not be able to resize, which can cause problems when displaying them at different screen resolutions.
  • Your tags may not support localization correctly because the length of a given text changes between languages.
  • Your widgets will display differently on different platforms, making it difficult to write multiplatform applications that look good.

The second method is more flexible. However, it also has disadvantages:

  • You have to do a lot of manual calculation to determine the correct size and location for each widget.
  • You must do some extra calculations to properly respond to window resizing.
  • Every time you change the window layout, you must redo all the calculations.

Even if you can still use either of these methods to layout a GUI, most of the time you’ll probably want to use a third and more convenient method implemented by a state-of-the-art GUI framework or toolkit: layout managers. Note: In some GUI frameworks, such as Tkinter, the layout manager is also called Geometry Managers.

Layout Managers automatically arrange widgets on the GUI based on your specific needs. It avoids the compatibility disadvantages of the first method and the complex calculations of the second method.

In the following sections, you’ll learn about PyQt’s built-in layout managers and how to use them to effectively lay out graphical components of GUI applications.

Various PyQt layout forms

In PyQt, widgets are graphical components that are used as building blocks for GUI applications. When you put a bunch of widgets on a window to create a GUI, you need to give them some order. You need to set the size and position of the widgets on the window, and you also need to define their behavior when users resize the base window.

Note: There are some incomplete sections in the official PyQt5 documentation. To solve this problem, you can look at the PyQt4 documentation, the Qt for Python documentation, or the original Qt documentation.

To arrange widgets on a PyQt window or form, use the following techniques:

  • Use on widgetsThe resize ()andMove ()To provide absolute size and location.
  • To achieveResizeEvent ()And dynamically calculates the size and position of the widget.
  • Use layout managers and let them do all the calculations and hard work for you.

These techniques typically correspond to the three different approaches for laying out guIs described in the previous section.

Again, calculating size and location dynamically can be a good idea, but most of the time, using a layout manager is better. In PyQt, a layout manager is a class that provides the functionality needed to automatically manage the size, location, and resizing behavior of widgets in a layout.

Using the Layout manager, you can automatically arrange child widgets within any parent, container, or widget. Using a layout manager ensures that you are taking full advantage of the available space on the GUI and that the application is still available when the user resizes the window.

To add widgets to the layout manager when the layout manager acts as a container for widgets and other layouts, call.addWidget () on the current layout. To add a layout to another layout, call.addLayout () on the current layout. You’ll learn more about nested layouts in the section “Nesting layouts to Build Complex GUIs.”

After you have added all the necessary widgets to the layout manager, you can use.setLayout () to set the layout manager on the given widget. You can set the layout manager on any subclass of QWidget, including Windows or forms.

Note: QMainWindow is a PyQt class that can be used to create main Widow-style Applications. This class has its own built-in layout manager. Therefore, if you are using QMainWindow, you generally do not need to set up the layout manager on the main window object.

All widgets in the layout are automatically set as children of the widgets that install the layout, not the layout itself. This is because widgets can only have other widgets as their parents, not the layout.

PyQt’s layout manager provides some cool features that make it easier for you to create beautiful GUI applications:

  • Handles the size and location of widgets without any calculation
  • Handles resizing and repositioning of widgets as the user resizes the base window
  • Adjust the label size to better support internationalization
  • Provides native window layouts for multi-platform applications

In the long run, using a layout manager will also greatly increase your productivity and improve the maintainability of your code.

PyQt provides four generic layout manager classes:

  • QHBoxLayoutArrange widgets in horizontal boxes.
  • QVBoxLayoutArrange widgets in vertical boxes.
  • QGridLayoutArrange the widgets in a grid.
  • QFormLayoutArrange the widgets in two columns.

In the next few sections, you’ll learn the basics of how to use these generic layout managers.

Use universal layout managers

When you create GUI applications using PyQt, you typically place widgets on Windows and forms using one or more of the four common layouts you saw at the end of the previous section.

In the next few sections, you’ll learn how to create and use four generic layout managers with the help of some examples.

Build a horizontal layout: QHBoxLayout

The space obtained from the parent layout or widget is divided into boxes or cells, and then each widget in the layout fills a Box.

QHBoxLayout is one of the two box layouts available in PyQt. This layout manager allows you to arrange widgets horizontally, one after the other. These widgets are added to the layout from left to right. This means that the first widget you add to your code will be the left-most widget in the layout.

To add a widget to a QHBoxLayout object, call. AddWidget (Widget, stretch, alignment) on the layout object. This method takes one required argument and two optional arguments:

  • widgetIs a mandatory parameter that holds the specific widget to add to the layout.
  • StretchIs an optional parameter that contains an integer representing the stretch factor to be applied to the widget. Widgets with a higher stretch factor grow more when they resize the window. The default is0, which indicates that the widget stretch factor is not assigned.
  • alignmentIs an optional parameter that contains both horizontal and vertical flags. You can combine these flags to produce the desired alignment of widgets within the cells they contain. The default is 0, which means that the widget will fill the entire cell.

Here is a small application that shows how to create a horizontal layout using QHBoxLayout. In this example, you will use the QPushButton object to better visualize where each widget is placed in the layout based on the order in which they are added to the code:

import sys

from PyQt5.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QPushButton,
    QWidget,
)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QHBoxLayout Example")
        # Create a QHBoxLayout instance
        layout = QHBoxLayout()
        # Add widgets to the layout
        layout.addWidget(QPushButton("Left-Most"))
        layout.addWidget(QPushButton("Center"), 1)
        layout.addWidget(QPushButton("Right-Most"), 2)
        # Set the layout on the application's window self.setLayout(layout) print(self.children()) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())Copy the code

On line 15, create a QHBoxLayout object called Layout. In lines 17 through 19, use.addWidget () to add the three buttons to the layout. Notice that you pass 1 and 2 to the Stretch parameter in the center and rightmost buttons, respectively. In line 21, use.setLayout () to set the layout to the top-level layout of the window.

If you run the application, you will see the following window on the screen:

The window contains three buttons arranged horizontally. Notice that the left-most button corresponds to the first button you add to your code. Therefore, the buttons are displayed in the same order (left to right) (top to bottom) that you would add them to your code.

The “Center” and “far right” buttons have different stretching coefficients, so they scale when you resize the window.

In addition, all buttons in the layout and the layout itself are set as children of the Window. This is done automatically by the layout object, which calls.setparent () internally on each widget. The call to print () on line 17 will print a list of children of Window on your terminal to prove this behavior.

Build a vertical layout: QVBoxLayout

QVBoxLayout arranges widgets vertically, one below the other. You can use this class to create vertical layouts and arrange widgets from top to bottom. Since QVBoxLayout is another box layout, its.addWidget () method works the same as in QHBoxLayout.

Here is a PyQt application that shows how to create and use the QVBoxLayout object to create a vertical arrangement of widgets in the GUI:

import sys

from PyQt5.QtWidgets import (
    QApplication,
    QPushButton,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QVBoxLayout Example")
        self.resize(270.110)
        # Create a QVBoxLayout instance
        layout = QVBoxLayout()
        # Add widgets to the layout
        layout.addWidget(QPushButton("Top"))
        layout.addWidget(QPushButton("Center"))
        layout.addWidget(QPushButton("Bottom"))
        # Set the layout on the application's window self.setLayout(layout) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())Copy the code

On line 16, you create an instance of QVBoxLayout. On lines 18 through 20, add three buttons to the layout. Finally, set the layout to the top level layout of the window.

If you run this application, the following window displays:

Your window displays three vertically arranged buttons, one below the other. The buttons are displayed in the same order (top to bottom) as you would add in the code (top to bottom).

Arrange widgets in a grid: QGridLayout

You can use QGridLayout to arrange widgets in a grid of rows and columns. Each widget will have a relative position in the grid. To define the location of a widget or a cell in a grid, use a pair of coordinates for a table (row, column). These coordinates should be integers starting from zero.

QGridLayout takes the available space of its parent, divides it into rows and columns, and then places each widget in its own cell or box. QGridLayout automatically calculates how many rows and columns the final layout will contain based on the number of widgets and their coordinates. If you do not add a widget to a given cell, QGridLayout leaves the cell empty.

To add a widget to a grid layout, call.addWidget () on the layout. This method has two different overloaded implementations:

  • addWidget(widget, row, column, alignment)willwidgetAdded to the(row, column)In the cell of.
  • AddWidget (Widget, fromRow, fromColumn, rowSpan, columnSpan, alignment)willwidgetAdd to a cell that spans multiple rows, columns, or both.

The first implementation takes the following parameters:

  • widgetIs a mandatory parameter to save specific widgets that you need to add to the layout.
  • rowIs a mandatory parameter that contains an integer that represents the coordinates of rows in the grid.
  • columnIs a mandatory parameter that contains an integer that represents the coordinates of the columns in the grid.
  • alignmentIs an optional parameter that holds the alignment of the widget within the cell it contains. The default is 0, which means that the widget will fill the entire cell.

Here is an example of how to create a widget grid using QGridLayout:

import sys

from PyQt5.QtWidgets import (
    QApplication,
    QGridLayout,
    QPushButton,
    QWidget,
)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QGridLayout Example")
        # Create a QGridLayout instance
        layout = QGridLayout()
        # Add widgets to the layout
        layout.addWidget(QPushButton("Button at (0, 0)"), 0.0)
        layout.addWidget(QPushButton("Button at (0, 1)"), 0.1)
        layout.addWidget(QPushButton("Button at (0, 2)"), 0.2)
        layout.addWidget(QPushButton("Button at (1, 0)"), 1.0)
        layout.addWidget(QPushButton("Button at (1, 1)"), 1.1)
        layout.addWidget(QPushButton("Button at (1, 2)"), 1.2)
        layout.addWidget(QPushButton("Button at (2, 0)"), 2.0)
        layout.addWidget(QPushButton("Button at (2, 1)"), 2.1)
        layout.addWidget(QPushButton("Button at (2, 2)"), 2.2)
        # Set the layout on the application's window self.setLayout(layout) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())Copy the code

On line 15, create the QGridLayout object. Then, on lines 17 through 25, use.addWidget () to add the widget to the layout. To see how a grid layout without assigned widgets manages cells, comment out one or more rows, and then run the application again.

If you run this code from the command line, you get a window like this:

Each widget in the QGridLayout object occupies a cell defined by a pair of coordinates that you provide in.addWidget (). The text on each button reflects these coordinates. The coordinates start from zero, so the first cell is at (0,0).

In the second implementation of.addWidget (), the widget and alignment parameters remain unchanged, and you have four other parameters that you can use to place the widget in multiple rows or columns:

  • fromRowAssigns an integer representing the line in which the widget will start.
  • fromColumnAssigns an integer representing the column in which the widget will start.
  • rowSpanAssigns an integer representing the number of rows the widget will occupy in the grid.
  • columnSpanAssigns an integer representing the number of columns the widget will occupy in the grid.

This is an application that shows how the.addWidget () variant works:

import sys

from PyQt5.QtWidgets import (
    QApplication,
    QGridLayout,
    QPushButton,
    QWidget,
)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QGridLayout Example")
        # Create a QGridLayout instance
        layout = QGridLayout()
        # Add widgets to the layout
        layout.addWidget(QPushButton("Button at (0, 0)"), 0.0)
        layout.addWidget(QPushButton("Button at (0, 1)"), 0.1)
        layout.addWidget(QPushButton("Button Spans two Cols"), 1.0.1.2)
        # Set the layout on the application's window self.setLayout(layout) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())Copy the code

In line 19, use the second implementation of.addWidget () to add a button that occupies two columns in the grid. The button starts on the second row (fromRow = 1) and the first column (fromColumn = 0). Finally, the button occupies one row (rowSpan = 1) and two columns (columnSpan = 2).

If you run the application, you will see the following window on the screen:

In this layout, you can have a widget occupy more than one cell, as with the “Cross two columns” button.

In the next chapter, we will see:

  • How to create a form quickly
  • Nested layouts to build complex GUIs
  • Use multi-page layouts and widgets
  • Lay out the main window of the application
  • Lay out the application dialog box
  • Manage input boxes in a PyQt layout

Read more

Someone poisoned the code! Use the PIP install command \ with caution

PIP 20.3 new release released! Getting rid of Python 2.x\

Learn the Hook function \ in Python in 5 minutes

Special recommendation \

Programmer’s guide to fish

For your selection of Silicon Valley geeks,

From FLAG giant developers, technology, venture capital first-hand news

\

Click below to read the article and join the community

Give it a thumbs up