Basics Intermediate Advanced
aialgorithmsapibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnewsnumpyprojectspythonstdlibtestingtoolsweb-devweb-scraping
- Laying Out Graphical Elements on a GUI
- Getting Stocked With a Gallery of PyQt Layouts
- Using General-Purpose Layout Managers
- Nesting Layouts to Build Complex GUIs
- Using Multipage Layouts and Widgets
- Laying Out the Application’s Main Window
- Laying Out the Application’s Dialogs
- Managing Space in a PyQt Layout
- Conclusion
Recommended Course

Creating PyQt Layouts for GUI Applications
1h 9m · 12 lessons

PyQt Layouts: Create Professional-Looking GUI Applications
Table of Contents
- Laying Out Graphical Elements on a GUI
- Getting Stocked With a Gallery of PyQt Layouts
- Using General-Purpose Layout Managers
- Nesting Layouts to Build Complex GUIs
- Using Multipage Layouts and Widgets
- Laying Out the Application’s Main Window
- Laying Out the Application’s Dialogs
- Managing Space in a PyQt Layout
- Conclusion
Recommended Course
PyQt’slayout managers provide a user-friendly and productive way of arranging graphical components, orwidgets, on a GUI. Laying out widgets properly will make yourGUI applications look polished and professional. Learning to do so efficiently and effectively is a fundamental skill for you to get up and running with GUI application development using Python and PyQt.
In this tutorial, you’ll learn:
- What the benefits are of using PyQt’slayout managers
- How to programmaticallylay out widgets on a GUI using PyQt’s layout managers
- How toselect the right layout manager for your GUI application
- How to lay out widgets inmain window–based anddialog-based applications
With this knowledge and skillset, you’ll be able to use Python and PyQt to create professional-looking GUI applications.
For a better understanding of how to use layout managers, some previous knowledge of how to createPyQt GUI applications and how to work withPyQt widgets would be helpful.
Free Bonus:5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Laying Out Graphical Elements on a GUI
When you’re creatinggraphical user interface (GUI) applications, a common issue is how to get your graphical components—buttons,menus, toolbars,labels, and so on—laid out coherently on your forms andwindows. This process is known asGUI layout, and it’s an important step in creating GUI applications.
In the past, if you wanted to lay out graphical components, orwidgets, on a window, then you would follow one of the following approaches:
- Decide on and manually set a static size and position for each widget on the window.
- Calculate and set the size and position of each widget dynamically.
The first approach is fairly direct, but it has at least the following drawbacks:
- Your windows will benon-resizable, which might cause problems when displaying them on different screen resolutions.
- Your labels might not supportlocalization properly because the length of a given text changes between languages.
- Your widgets will display differently on different platforms, which makes it difficult to writemultiplatform applications that look good.
The second approach is more flexible. However, it also has drawbacks:
- You have to do a lot of manual calculations to determine the rightsize andposition of each widget.
- You have to do some extra calculations to respond correctly towindow resizing.
- You have to redo all the calculations any time youmodify the layout of your window.
Even though you can still use either of these two approaches to lay out your GUIs, most of the time you’ll want to use a third and more convenient approach implemented by most modernGUI frameworks or toolkits: layout managers.
Note: In some GUI frameworks, such asTkinter, layout managers are also referred to asgeometry managers.
Layout managers automatically arrange widgets on a GUI according to your specific needs. They avoid the compatibility drawbacks of the first approach as well as the annoying and complicated calculations of the second approach.
In the following sections, you’ll learn about PyQt’s built-in layout managers and how to use them to effectively lay out the graphical components of your GUI applications.
Getting Stocked With a Gallery of PyQt Layouts
In PyQt, widgets are graphical components that you use as building blocks for your GUI applications. When you place a bunch of widgets on a window to create a GUI, you need to give them some order. You need to set the widgets’ size and position on the window, and you also need to define their behavior for when the user resizes the underlying window.
Note: Unfortunately, PyQt5’sofficial documentation has some incomplete sections. To work around this, you can check out thePyQt4 documentation, theQt for Python documentation, or the originalQt documentation.
In this tutorial, you’ll find that most links will take you to the original Qt documentation, which is a better source of information in most cases.
To arrange the widgets on windows or forms in PyQt, you can use the following techniques:
- Use
.resize()and.move()on your widgets to provide an absolute size and position. - Reimplement
.resizeEvent()and calculate your widgets’ size and position dynamically. - Use layout managers and let them do all the calculations and hard work for you.
These techniques generally correspond to the three different approaches for laying out a GUI that you saw in the previous section.
Again, calculating the size and position dynamically might be a good approach, but most of the time you’ll be better off usinglayout managers. In PyQt, layout managers are classes that provide the required functionality to automatically manage the size, position, and resizing behavior of the widgets in the layout.
With layout managers, you can automatically arrangechild widgets within anyparent, or container, widget. Using layout managers will ensure that you make good use of the available space on your GUI and also that your application remains usable when the user resizes the window.
Layout managers work as containers for both widgets and other layouts. To add widgets to a layout manager, you call.addWidget() on the layout at hand. To add a layout to another layout, you call.addLayout() on the layout at hand. You’ll dive deeper into nesting layouts in the sectionNesting Layouts to Build Complex GUIs.
Once you’ve added all the required widgets to a layout manager, you set the layout manager on a given widget using.setLayout(). You can set a layout manager on any subclasses ofQWidget, including windows or forms.
Note:QMainWindow is a PyQt class that you can use to createmain window–style applications. This class has its ownbuilt-in layout manager. So, if you’re usingQMainWindow, then you commonly won’t need to set a layout manager on your main window objects.
All the widgets in a layout are automatically set as children of the widget on which you install the layout, not of the layout itself. That’s because widgets can have only other widgets, not layouts, as their parent.
PyQt’s layout managers provide some cool features that make your life a lot easier when it comes to creating good-looking GUI applications:
- Handling thesize andposition of widgets without the need for any calculation
- Handling theresizing andrepositioning of widget when the user resizes the underlying window
- Resizing labels to better supportinternationalization
- Providing a native window layout formultiplatform applications
Using layout managers will also dramatically increase your productivity and improve your code’s maintainability in the long term.
PyQt provides four general-purpose layout manager classes:
QHBoxLayoutarranges widgets in a horizontal box.QVBoxLayoutarranges widgets in a vertical box.QGridLayoutarranges widgets in a grid.QFormLayoutarranges widgets in two columns.
In the next few sections, you’ll learn the basics of how to use these general-purpose layout managers.
Using General-Purpose Layout Managers
When creating GUI applications with PyQt, you’ll often use one or more of the four general-purpose layouts that you saw at the end of the previous section to get your widget laid out on your windows and forms.
In the next few sections, you’ll learn how to create and use the four general-purpose layout managers with the help of some examples.
Building Horizontal Layouts:QHBoxLayout
Box layout managers take the space they get from their parent layout or widget, divide it up into a number of boxes, orcells, and make each widget in the layout fill one box.
QHBoxLayout is one of the two available box layouts in PyQt. This layout manager allows you to arrange widgetshorizontally, one next to the other. The widgets are added to the layout from left to right. This means that the widget that you add first in your code will be the left-most widget in the layout.
To add widgets to aQHBoxLayout object, you call.addWidget(widget, stretch, alignment) on the layout object. This method takes one required argument and two optional arguments:
widgetis a required argument that holds the specific widget that you want to add to the layout.stretchis an optional argument that holds an integer number representing thestretch factor to apply towidget. Widgets with higher stretch factors grow more on window resizing. It defaults to0, which means that the widget has no stretch factor assigned.alignmentis an optional argument that holds horizontal and verticalflags. You can combine these flags to produce the desiredalignment of the widget inside its containing cell. It defaults to0, which means that the widget will fill the entire cell.
Here’s a small application that shows how to create a horizontal layout usingQHBoxLayout. In this example, you’ll useQPushButton objects to better visualize where each widget will be placed in the layout according to the order in which you add the widgets to your code:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QHBoxLayout, 6QPushButton, 7QWidget, 8) 910classWindow(QWidget):11def__init__(self):12super().__init__()13self.setWindowTitle("QHBoxLayout Example")14# Create a QHBoxLayout instance15layout=QHBoxLayout()16# Add widgets to the layout17layout.addWidget(QPushButton("Left-Most"))18layout.addWidget(QPushButton("Center"),1)19layout.addWidget(QPushButton("Right-Most"),2)20# Set the layout on the application's window21self.setLayout(layout)22print(self.children())2324if__name__=="__main__":25app=QApplication(sys.argv)26window=Window()27window.show()28sys.exit(app.exec_())On line 15, you create aQHBoxLayout object calledlayout. On lines 17 to 19, you add three buttons tolayout using.addWidget(). Note that you pass1 and2 to thestretch parameter in theCenter andRight-Most buttons, respectively. On line 21, you setlayout as your window’s top-level layout using.setLayout().
Note: If you’re new to GUI programming with PyQt, then you can take a look atPython and PyQt: Building a GUI Desktop Calculator to get a better idea of how to create a GUI application with PyQt.
If yourun this application, then you’ll get the following window on your screen:

This window contains three buttons arranged in a horizontal fashion. Note that theLeft-Most button corresponds to the first button that you add in your code. So, buttons are shown in the same order (from left to right) that you add them in your code (from top to bottom).
TheCenter andRight-Most buttons have different stretch factors, so they expand in proportion to those factors when you resize the window.
Additionally, all the buttons inlayout and the layout itself are set as children ofWindow. This is automatically done by the layout object, which internally calls.setParent() on each widget. The call toprint() on line 22 prints a list of the children ofWindow on yourterminal as evidence of this behavior.
Building Vertical Layouts:QVBoxLayout
QVBoxLayout arranges widgetsvertically, one below the other. You can use this class to create vertical layouts and arrange your widgets from top to bottom. SinceQVBoxLayout is another box layout, its.addWidget() method works the same as inQHBoxLayout.
Here’s a PyQt application that shows how to create and use aQVBoxLayout object for creating vertical arrangements of widgets in your GUIs:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QPushButton, 6QVBoxLayout, 7QWidget, 8) 910classWindow(QWidget):11def__init__(self):12super().__init__()13self.setWindowTitle("QVBoxLayout Example")14self.resize(270,110)15# Create a QVBoxLayout instance16layout=QVBoxLayout()17# Add widgets to the layout18layout.addWidget(QPushButton("Top"))19layout.addWidget(QPushButton("Center"))20layout.addWidget(QPushButton("Bottom"))21# Set the layout on the application's window22self.setLayout(layout)2324if__name__=="__main__":25app=QApplication(sys.argv)26window=Window()27window.show()28sys.exit(app.exec_())On line 16, you create an instance ofQVBoxLayout. On lines 18 to 20, you add three buttons tolayout. Finally, you setlayout as your window’s top-level layout.
If you run this application, then you’ll get the following window:

Your window shows three buttons in a vertical arrangement, one below the other. The buttons appear in the same order (from top to bottom) as you add them in your code (from top to bottom).
Arranging Widgets in a Grid:QGridLayout
You can useQGridLayout to arrange widgets in agrid of rows and columns. Each widget will have a relative position in the grid. To define a widget’s position, or cell in the grid, you use a pair of coordinates of the form(row, column). These coordinates should be zero-basedinteger numbers.
QGridLayout takes the available space on its parent, divides it into rows and columns, and places each widget into its own cell or box.QGridLayout automatically figures out how many rows and columns the final layout will have depending on the number of widgets and their coordinates. If you don’t add a widget to a given cell, thenQGridLayout will leave that cell empty.
To add widgets to a grid layout, you call.addWidget() on the layout. This method has two differentoverloaded implementations:
addWidget(widget, row, column, alignment)addswidgetto the cell at (row,column).addWidget(widget, fromRow, fromColumn, rowSpan, columnSpan, alignment)addswidgetto the cell, spanning multiple rows, columns, or both.
The first implementation takes the following arguments:
widgetis a required argument that holds the specific widget that you need to add to the layout.rowis a required argument that holds an integer representing the coordinate of a row in the grid.columnis a required argument that holds an integer representing the coordinate of a column in the grid.alignmentis an optional argument that holds the alignment of the widget inside its containing cell. It defaults to0, which means that the widget will fill the entire cell.
Here’s an example of how to useQGridLayout to create a grid of widgets:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QGridLayout, 6QPushButton, 7QWidget, 8) 910classWindow(QWidget):11def__init__(self):12super().__init__()13self.setWindowTitle("QGridLayout Example")14# Create a QGridLayout instance15layout=QGridLayout()16# Add widgets to the layout17layout.addWidget(QPushButton("Button at (0, 0)"),0,0)18layout.addWidget(QPushButton("Button at (0, 1)"),0,1)19layout.addWidget(QPushButton("Button at (0, 2)"),0,2)20layout.addWidget(QPushButton("Button at (1, 0)"),1,0)21layout.addWidget(QPushButton("Button at (1, 1)"),1,1)22layout.addWidget(QPushButton("Button at (1, 2)"),1,2)23layout.addWidget(QPushButton("Button at (2, 0)"),2,0)24layout.addWidget(QPushButton("Button at (2, 1)"),2,1)25layout.addWidget(QPushButton("Button at (2, 2)"),2,2)26# Set the layout on the application's window27self.setLayout(layout)2829if__name__=="__main__":30app=QApplication(sys.argv)31window=Window()32window.show()33sys.exit(app.exec_())On line 15, you create theQGridLayout object. Then, on lines 17 to 25, you add widgets to the layout using.addWidget(). To see how grid layouts manage cells without an assigned widget, comment out one or more of these lines and run the application again.
If you run this code from your command line, then you’ll get a window like this:

Each widget in theQGridLayout object occupies the cell defined by the pair of coordinates that you provide in.addWidget(). The text on each button reflects those coordinates. The coordinates are zero-based, so the first cell is at(0, 0).
In the second implementation of.addWidget(), the argumentswidget andalignment stay the same, and you have four additional arguments that allow you to place the widget across several rows or columns:
fromRowtakes an integer number that represents the row in which the widget will start.fromColumntakes an integer number that represents the column in which the widget will start.rowSpantakes an integer number that represents the number of rows that the widget will occupy in the grid.columnSpantakes an integer number that represents the number of columns that the widget will occupy in the grid.
Here’s an application that shows how this variation of.addWidget() works:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QGridLayout, 6QPushButton, 7QWidget, 8) 910classWindow(QWidget):11def__init__(self):12super().__init__()13self.setWindowTitle("QGridLayout Example")14# Create a QGridLayout instance15layout=QGridLayout()16# Add widgets to the layout17layout.addWidget(QPushButton("Button at (0, 0)"),0,0)18layout.addWidget(QPushButton("Button at (0, 1)"),0,1)19layout.addWidget(QPushButton("Button Spans two Cols"),1,0,1,2)20# Set the layout on the application's window21self.setLayout(layout)2223if__name__=="__main__":24app=QApplication(sys.argv)25window=Window()26window.show()27sys.exit(app.exec_())On line 19, you use the second implementation of.addWidget() to add a button that occupies two columns in the grid. The button starts at the second row (fromRow=1) and at the first column (fromColumn=0). Finally, the button occupies one row (rowSpan=1) and two columns (columnSpan=2).
Note: SincePyQt is a Python binding forQt, which is a set ofC++ libraries, sometimes you can’t usekeyword arguments when calling PyQt methods. The keyword arguments used in the above paragraph have the sole purpose of showing what value is assigned to each argument.
Here’s the window that you’ll see on your screen if you run this application:

In this kind of layout, you can make a widget occupy more than one cell, just as you did with theButton Spans two Cols button.
Creating Forms Quickly:QFormLayout
If you’re constantly creating forms to perform actions like inputting data into a database, thenQFormLayout is for you. This class arranges widgets in atwo-column layout. The first column usually displays alabel describing the intended input, and the second column generally containsinput widgets such asQLineEdit,QComboBox, orQSpinBox that allow the user to enter or edit data.
To add widgets to a form layout, you use.addRow(). This method has several variations but, most of the time, you’ll choose from the following two:
.addRow(label, field)adds a new row to the bottom of a form layout. The row should contain aQLabelobject (label) and an input widget (field)..addRow(labelText, field)automatically creates and adds a newQLabelobject withlabelTextas its text.fieldholds an input widget.
Here’s a sample application that uses aQFormLayout object to arrange widgets:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QFormLayout, 6QLabel, 7QLineEdit, 8QWidget, 9)1011classWindow(QWidget):12def__init__(self):13super().__init__()14self.setWindowTitle("QFormLayout Example")15self.resize(270,110)16# Create a QFormLayout instance17layout=QFormLayout()18# Add widgets to the layout19layout.addRow("Name:",QLineEdit())20layout.addRow("Job:",QLineEdit())21emailLabel=QLabel("Email:")22layout.addRow(emailLabel,QLineEdit())23# Set the layout on the application's window24self.setLayout(layout)2526if__name__=="__main__":27app=QApplication(sys.argv)28window=Window()29window.show()30sys.exit(app.exec_())On line 17, you create aQFormLayout object. Then, on lines 19 to 22, you add some rows to the layout. Note that on lines 19 and 20, you use the second variation of the method, and on line 22, you use the first variation, passing aQLabel object as the first argument to.addRow().
If you run this code, then you’ll get the following window on your screen:

With aQFormLayout, you can organize your widgets in a two-column arrangement. The first column contains labels that ask the user for some information. The second column shows widgets that allow the user to input or edit that information.
Nesting Layouts to Build Complex GUIs
You can usenested layouts to create complex GUIs that would be difficult to create using one of the general-purpose PyQt’s layout managers. To do that, you need to call.addLayout() on anouter layout. This way, theinner layout becomes a child of the outer layout.
Suppose you need to create a dialog that shows a label and a line edit in a form layout, and below those widgets you want to place several checkboxes in a vertical layout. Here’s a mock-up of what your dialog should look like:

The blue rectangle represents your outer layout. The green rectangle is the form layout that will hold the label and line edit. The red rectangle is the vertical layout to hold the option checkboxes. Both the green layout and the red layout are nested into the blue one, which is a vertical layout.
Here’s an example of how to build this layout using PyQt:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QCheckBox, 6QFormLayout, 7QLineEdit, 8QVBoxLayout, 9QWidget,10)1112classWindow(QWidget):13def__init__(self):14super().__init__()15self.setWindowTitle("Nested Layouts Example")16# Create an outer layout17outerLayout=QVBoxLayout()18# Create a form layout for the label and line edit19topLayout=QFormLayout()20# Add a label and a line edit to the form layout21topLayout.addRow("Some Text:",QLineEdit())22# Create a layout for the checkboxes23optionsLayout=QVBoxLayout()24# Add some checkboxes to the layout25optionsLayout.addWidget(QCheckBox("Option one"))26optionsLayout.addWidget(QCheckBox("Option two"))27optionsLayout.addWidget(QCheckBox("Option three"))28# Nest the inner layouts into the outer layout29outerLayout.addLayout(topLayout)30outerLayout.addLayout(optionsLayout)31# Set the window's main layout32self.setLayout(outerLayout)3334if__name__=="__main__":35app=QApplication(sys.argv)36window=Window()37window.show()38sys.exit(app.exec_())Here’s what you’re doing in this code:
- On line 17, you create the outer, or top-level, layout, which you’ll use as a parent layout and as the main layout of your window. In this case, you use
QVBoxLayoutbecause you want your widgets to be arranged vertically on your form. In your mock-up, this is the blue layout. - On line 19, you create a form layout to hold a label and a line edit.
- On line 21, you add the required widgets to the layout. This is equivalent to your green layout.
- On line 23, you create a vertical layout to hold the checkboxes.
- On lines 25 to 27, you add the required checkboxes. This is your red layout.
- On lines 29 and 30, you nest
topLayoutandoptionsLayoutunder theouterLayout.
That’s it! If you run the application, then you’ll see a window like the following:

In this application, you nest two different layouts under an outer layout to create a general layout for your window. At the top of the window, you use a horizontal layout to place a label and a line edit. Then you place some checkboxes below that using a vertical layout.
Using Multipage Layouts and Widgets
So far, you’ve seen how to use traditional or general-purpose layout managers to arrange the widgets in your application’s windows. These layout managers will arrange widgets on asingle-page layout. In other words, your GUI will always show the same set of widgets to the user.
Sometimes you need to create a layout that shows a different set of widgets in response to certain user actions on the GUI. For example, if you’re creating a preferences dialog for a given application, then you might want to present the user with atab-based, ormultipage, layout in which each tab or page contains a different set of closely related options. Every time the user clicks on a tab or page, the application shows a different set of widgets.
PyQt provides a built-in layout calledQStackedLayout and some convenient widgets likeQTabWidget that will allow you to create this kind of multipage layout. The next few sections will walk you through some of these tools.
Creating a Stack of Widgets
QStackedLayout provides a layout manager that will allow you to arrange your widgets on astack, one on top of the other. In this kind of layout, only one widget is visible at a given time.
To populate a stacked layout with widgets, you need to call.addWidget() on the layout object. This will add each widget to the end of the layout’s internal list of widgets. You can also insert or remove a widget at a given position in the list of widgets using.insertWidget(index) or.removeWidget(widget), respectively.
Each widget in the list of widgets is displayed as an independent page. If you want to show several widgets on a page, then use aQWidget object for each page and set an appropriate layout of widgets to the page widget. If you need to get the total number of widgets (pages) in the layout, then you can call.count().
An important point to keep in mind when working withQStackedLayout objects is that you need to explicitly provide a mechanism to switch between pages. Otherwise, your layout will always show the same page to the user. To switch between pages, you need to call.setCurrentIndex() on the layout object.
Here’s an example that shows how to use a stacked layout with a combo box for switching between pages:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QComboBox, 6QFormLayout, 7QLineEdit, 8QStackedLayout, 9QVBoxLayout,10QWidget,11)1213classWindow(QWidget):14def__init__(self):15super().__init__()16self.setWindowTitle("QStackedLayout Example")17# Create a top-level layout18layout=QVBoxLayout()19self.setLayout(layout)20# Create and connect the combo box to switch between pages21self.pageCombo=QComboBox()22self.pageCombo.addItems(["Page 1","Page 2"])23self.pageCombo.activated.connect(self.switchPage)24# Create the stacked layout25self.stackedLayout=QStackedLayout()26# Create the first page27self.page1=QWidget()28self.page1Layout=QFormLayout()29self.page1Layout.addRow("Name:",QLineEdit())30self.page1Layout.addRow("Address:",QLineEdit())31self.page1.setLayout(self.page1Layout)32self.stackedLayout.addWidget(self.page1)33# Create the second page34self.page2=QWidget()35self.page2Layout=QFormLayout()36self.page2Layout.addRow("Job:",QLineEdit())37self.page2Layout.addRow("Department:",QLineEdit())38self.page2.setLayout(self.page2Layout)39self.stackedLayout.addWidget(self.page2)40# Add the combo box and the stacked layout to the top-level layout41layout.addWidget(self.pageCombo)42layout.addLayout(self.stackedLayout)4344defswitchPage(self):45self.stackedLayout.setCurrentIndex(self.pageCombo.currentIndex())4647if__name__=="__main__":48app=QApplication(sys.argv)49window=Window()50window.show()51sys.exit(app.exec_())On lines 21 to 23, you create aQComboBox object that will allow you to switch between the pages in the layout. Then you add two options to the combo box in alist and connect it to.switchPage(), which is intended to handle page switching.
Inside.switchPage(), you call.setCurrentIndex() on the layout object, passing the current index of the combo box as an argument. This way, when the user changes the option in the combo box, the page on the stacked layout will change accordingly.
On line 25, you create theQStackedLayout object. On lines 27 to 32, you add the first page to the layout, and on lines 34 to 39, you add the second page. Each page is represented by aQWidget object that contains several widgets in a convenient layout.
The final step to get everything working is to add the combo box and the layout to the application’s main layout.
Here’s how your application behaves now:

In this case, you have two pages in your application’s layout. Each page is represented by aQWidget object. When you select a new page in the combo box on the top of the window, the layout changes to show the selected page.
Note: PyQt provides a convenient class calledQStackedWidget, which is built on top ofQStackedLayout. You can also use this class to create multipage layouts.
This class provides a stack of widgets in which only one widget is visible at a time. Just like stacked layouts,QStackedWidget doesn’t provide an intrinsic mechanism for switching between pages.
Besides stacked layout and stacked widget, you can useQTabWidget to create a multipage user interface. You’ll learn how in the next section.
Using PyQt’s Tab Widgets
Another popular way of creating multipage arrangements in PyQt is by using a class calledQTabWidget. This class provides atab bar and apage area. You use the tab bar to switch between pages and the page area to display the page associated with the selected tab.
The tab bar is located at the top of the page area by default. However, you can change this behavior using.setTabPosition() and one of four possibletab positions:
| Tab Position | Tab Bar Location |
|---|---|
QTabWidget.North | Top of the pages |
QTabWidget.South | Bottom of the pages |
QTabWidget.West | Left of the pages |
QTabWidget.East | Right of the pages |
To add tabs to a tab widget, you use.addTab(). This method has two variations, or overloaded implementations:
.addTab(page, label).addTab(page, icon, label)
In both cases, the method adds a new tab, withlabel as the tab’s title.page needs to be a widget representing the page associated with the tab at hand.
In the second variation of the method,icon needs to be aQIcon object. If you pass an icon to.addTab(), then that icon will be shown to the left of the tab’s title.
A common practice when creating tab widgets is to use aQWidget object for each page. This way, you’ll be able to add extra widgets to the page using a layout containing the required widgets.
Most of the time, you’ll use tab widgets to create dialogs for your GUI applications. This kind of layout allows you to present the user with several options in a relatively small space. You can also take advantage of the tab system to organize your options according to some classification criteria.
Here’s a sample application that shows the basics of how to create and use aQTabWidget object:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QCheckBox, 6QTabWidget, 7QVBoxLayout, 8QWidget, 9)1011classWindow(QWidget):12def__init__(self):13super().__init__()14self.setWindowTitle("QTabWidget Example")15self.resize(270,110)16# Create a top-level layout17layout=QVBoxLayout()18self.setLayout(layout)19# Create the tab widget with two tabs20tabs=QTabWidget()21tabs.addTab(self.generalTabUI(),"General")22tabs.addTab(self.networkTabUI(),"Network")23layout.addWidget(tabs)2425defgeneralTabUI(self):26"""Create the General page UI."""27generalTab=QWidget()28layout=QVBoxLayout()29layout.addWidget(QCheckBox("General Option 1"))30layout.addWidget(QCheckBox("General Option 2"))31generalTab.setLayout(layout)32returngeneralTab3334defnetworkTabUI(self):35"""Create the Network page UI."""36networkTab=QWidget()37layout=QVBoxLayout()38layout.addWidget(QCheckBox("Network Option 1"))39layout.addWidget(QCheckBox("Network Option 2"))40networkTab.setLayout(layout)41returnnetworkTab4243if__name__=="__main__":44app=QApplication(sys.argv)45window=Window()46window.show()47sys.exit(app.exec_())In this example, you use a tab widget to present the user with a concise dialog that shows options related to theGeneral andNetwork sections of a hypothetical preferences menu. On line 20, you create theQTabWidget object. Then you add two tabs to the tab widget using.addTab().
In.generalTabUI() andnetworkTabUI(), you create the specific GUI for each tab. To do this, you use aQWidget object, aQVBoxLayout object, and some checkboxes to hold the options.
If you run the application now, then you’ll get the following dialog on your screen:

That’s it! You have a fully functional tab-based GUI. Note that to switch between pages, you just need to click the corresponding tab.
Laying Out the Application’s Main Window
If you’re using PyQt to create your GUI applications, then most of the time you’ll useQMainWindow to create a GUI on top of it. This class allows you to createmain window–style applications.QMainWindow ships with its ownpredefined layout. This layout will allow you to add the following graphical components to your main window:
- Amenu bar at the top of the window
- One or moretoolbars at any of the four sides of the window
- Astatus bar at the bottom of the window
- One or moredock widgets at any of the four sides of the window (but without occupying the toolbars area)
- Acentral widget at the very center of the window
For most applications, all these graphical components are optional except for the central widget, which is required to make your application work.
Note: If you’re creating GUI applications usingQMainWindow, then youmust have a central widget, even if it’s just a placeholder.
Some applications use a unique and fully functional widget as their central widget. For example, if you’re coding a text editor, then you’ll likely use aQTextEdit object as your editor’s central widget.
Other kinds of GUI applications might require a more elaborate central widget. In that case, you can use aQWidget object as your central widget and then create a layout containing the specific widget arrangement that you need for your application’s GUI. The final step is to set that layout as your central widget’s layout.
Most of the time, the layout thatQMainWindow offers is enough to create any kind of GUI application. This layout will effectively manage the behavior of the widgets on the window, so you don’t have to worry about that.
Laying Out the Application’s Dialogs
GUI applications are commonly built using a main window and one or moredialogs.Dialogs are small windows that allow you to communicate with your users. PyQt providesQDialog to handle the creation of dialogs.
UnlikeQMainWindow,QDialog doesn’t have a predefined or default top-level layout. That’s because dialogs can be quite varied and include a wide range of widget arrangements and combinations.
Once you place all the widgets on a dialog’s GUI, you need to set a top-level layout on that dialog. To do this, you have to call.setLayout() on the dialog object just like you’d do with any other widget.
Here’s adialog-style application that shows how to set a top-level layout to aQDialog object:
1importsys 2 3fromPyQt5.QtWidgetsimport( 4QApplication, 5QDialog, 6QDialogButtonBox, 7QFormLayout, 8QLineEdit, 9QVBoxLayout,10)1112classDialog(QDialog):13def__init__(self):14super().__init__()15self.setWindowTitle("QDialog's Top-Level Layout Example")16dlgLayout=QVBoxLayout()17# Create a form layout and add widgets18formLayout=QFormLayout()19formLayout.addRow("Name:",QLineEdit())20formLayout.addRow("Job:",QLineEdit())21formLayout.addRow("Email:",QLineEdit())22# Add a button box23btnBox=QDialogButtonBox()24btnBox.setStandardButtons(25QDialogButtonBox.Ok|QDialogButtonBox.Cancel26)27# Set the layout on the dialog28dlgLayout.addLayout(formLayout)29dlgLayout.addWidget(btnBox)30self.setLayout(dlgLayout)3132if__name__=="__main__":33app=QApplication(sys.argv)34dlg=Dialog()35dlg.show()36sys.exit(app.exec_())In this case, the application’s window inherits fromQDialog, so you have a dialog-style application. On line 16, you create the layout that you’ll use as the dialog’s top-level layout. On lines 18 to 21, you create a form layout to arrange some widgets in a form.
On line 24, you add aQDialogButtonBox object. You’ll often useQDialogButtonBox to handle the buttons on a dialog. In this example, you use two buttons, anOk button and aCancel button. These buttons won’t have any functionality—they’re just intended to make the dialog more realistic.
Once you have all the widgets and layouts in place, you can add them to the top-level layout. That’s what you do on lines 28 and 29. The final step, on line 30, is to set the top-level layout as your dialog’s layout using.setLayout().
If you run this application, then you’ll see the following window on your screen:

It’s a best practice to set a top-level layout for all your dialogs. This ensures that the dialog’s GUI will behave coherently when the user resizes the underlying window. Otherwise, your dialogs could appear disorganized and unpolished in the user’s eyes.
Managing Space in a PyQt Layout
When it comes to using PyQt’s layout managers to arrange the widgets on a window or form, managing space—empty space, space between widgets, and so on—is a common issue. Being able to manage this space is an important skill to have.
Internally, layouts manage the available space on a window using some of the following widget properties:
.sizeHint()contains the widget’s recommended size.minimumSizeHint()contains the smallest size the widget can have while remaining usable.sizePolicy()holds the default behavior of a widget in a layout
Layouts use these properties to automatically position and resize widgets, assigning a given amount of space to each widget according to the available space. This ensures that widgets are consistently arranged and remain usable.
In the next three sections, you’ll learn how the different types of layouts manage space in PyQt.
Managing Space in Box Layouts
Box layouts do a great job when it comes to distributing available space between widgets. However, sometime their default behavior isn’t enough, and you need to manually handle the available space. To help you out in this situation, PyQt providesQSpacerItem. This class allows you to add blank space (or empty boxes) to a box layout.
Normally, you don’t need to useQSpacerItem directly. Instead, you call some of the following methods on your box layout objects:
.addSpacing(i)adds a non-stretchable space (or empty box) of fixed sizeito the layout.imust be an integer representing the size of the space in pixels..addStretch(i)adds a stretchable space with a minimum size of0and a stretch factorito a box layout.imust be an integer..insertSpacing(index, size)inserts a non-stretchable space at positionindex, with sizesize. Ifindexis negative, then the space is added at the end of the box layout.insertStretch(index, stretch)inserts a stretchable space at positionindex, with a minimum size of0and a stretch factor ofstretch. Ifindexis negative, then the space is added at the end of the box layout.
Stretchable spacers will expand or shrink to fill empty space when the user resizes the underlying window.Non-stretchable spacers will remain the same size regardless of the changes in the size of the underlying window.
Go back to the example of how to use vertical layouts and run that application again. If you pull down the border of the window, then you’ll notice that more space appears between the buttons the further down you pull:

This happens because the layout handles the newly available space by automatically expanding its boxes. You can change this behavior by adding a stretchableQSpacerItem object to the end of the layout.
In your example’s code, update the initializer ofWindow as follows:
classWindow(QWidget):def__init__(self):super().__init__()self.setWindowTitle("QVBoxLayout Example")self.resize(270,110)# Create a QVBoxLayout instancelayout=QVBoxLayout()# Add widgets to the layoutlayout.addWidget(QPushButton("Top"))layout.addWidget(QPushButton("Center"))layout.addWidget(QPushButton("Bottom"))layout.addStretch()# Set the layout on the application's windowself.setLayout(layout)In the highlighted line, you add a stretchableQSpacerItem object to the end of the layout by calling.addStretch() on the layout. If you run the application again, then you’ll get the following behavior:

Now all the extra space is automatically assigned to the stretchableQSpacerItem object at the bottom of the layout without affecting the position or size of the rest of the widgets. You can use this and other space management techniques to make your GUI applications look good and polished.
Managing Space in Grid and Form Layouts
Grid and form layouts handle available space in a different way. In these types of layouts, you can handle only the vertical and horizontal space between widgets. These layouts provide three methods to manage these spaces:
setSpacing(spacing)sets both the vertical and the horizontal spacing between widgets tospacing.setVerticalSpacing(spacing)sets only the vertical spacing between widgets in the layout tospacing.setHorizontalSpacing(spacing)sets only the horizontal spacing between widgets in the layout tospacing.
In all cases,spacing is an integer representing pixels. Now go back to the example on how to create a form layout and update the initializer ofWindow like this:
classWindow(QWidget):def__init__(self):super().__init__()self.setWindowTitle("QFormLayout Example")self.resize(270,110)# Create a QHBoxLayout instancelayout=QFormLayout()# Add widgets to the layoutlayout.setVerticalSpacing(30)layout.addRow("Name:",QLineEdit())layout.addRow("Job:",QLineEdit())emailLabel=QLabel("Email:")layout.addRow(emailLabel,QLineEdit())# Set the layout on the application's windowself.setLayout(layout)In the highlighted line, you set the vertical space between widgets to30 pixels. If you run the application again, then you’ll see the following window:

Now there’s more space between the rows of widgets. You can also try modifying the example of how to use a grid layout by adding some vertical or horizontal space just to see how all these spacing mechanisms work.
Conclusion
Creating high-qualityGUI applications requires laying out all the graphical components in a coherent and polished arrangement. In PyQt, an effective way of doing that is to use PyQt’slayout managers, which provide a user-friendly and productive way of approaching this task.
In this tutorial, you’ve learned:
- What thebenefits are of properly laying out the widgets on a GUI
- How to programmatically arrange widgets using PyQt’s built-inlayout managers
- Which layout manager to use for your specificuse case
- How to lay outmain window–style anddialog-style applications in PyQt
With this knowledge, you’ll be able to create good-looking and professional GUI applications using PyQt’s built-in layouts.
Recommended Course
🐍 Python Tricks 💌
Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

AboutLeodanis Pozo Ramos
Leodanis is a self-taught Python developer, educator, and technical writer with over 10 years of experience.
» More about LeodanisMasterReal-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
MasterReal-World Python Skills
With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
What Do You Think?
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.
Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!
Keep Learning
Keep reading Real Python by creating a free account or signing in:
Already have an account?Sign-In






