PyQt5 is a comprehensive Python binding for Qt, a powerful cross-platform GUI toolkit. With PyQt5, you can build desktop applications for Windows, MacOS, Linux, as well as mobile apps for Android and iOS. In this guide, we will cover the basics of using PyQt5 to build graphical user interfaces in Python.
Getting Started with PyQt5
To get started with PyQt5, first install it using pip:
pip install PyQt5
This will install PyQt5 along with its dependencies. Now create a Python file and import the necessary PyQt5 modules:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton,
QLabel, QLineEdit, QGridLayout)
This imports QApplication which is the heart of all PyQt5 applications, QWidget which is the base class for all UI elements, and some common UI elements like QPushButton, QLabel, QLineEdit.
Next, create a subclass of QWidget for the application window and override its __init__ method to add UI elements:
class Window(QWidget):
def __init__(self):
super().__init__()
# Add UI elements here
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()
This creates the application object, instantiates the window, shows it and starts the event loop. Now let‘s start adding some UI elements.
Adding UI Elements
Setting Window Geometry with setGeometry()
We can set the initial size and position of the window using the setGeometry() method. It takes four arguments:
- x position
- y position
- width
- height
For example:
self.setGeometry(100, 100, 800, 600)
This will set the window size to 800×600 pixels and place it 100 pixels from the top-left of the screen.
You can also retrieve the geometry using the geometry() method which returns a QRect.
Setting Window Title and Icon
Use the setWindowTitle() method to set the title displayed in the titlebar:
self.setWindowTitle("My App")
And the setWindowIcon() method to set the window icon from a .png image:
icon = QIcon("icon.png")
self.setWindowIcon(icon)
Make sure the icon image is 64×64 pixels.
Adding Push Buttons
The QPushButton class represents a clickable button:
button = QPushButton("Click Me")
We can get notified when it‘s clicked by connecting to its clicked signal:
button.clicked.connect(self.buttonClicked)
def buttonClicked(self):
print("Button clicked!")
Use the setGeometry() method to position it in the desired location. Other useful QPushButton methods are:
setText()– Set the display textsetIcon()– Set the icon imagesetEnabled()– Disable/enable the buttonsetCursor()– Change mouse cursor when hovering
Adding Input Boxes with QLineEdit
QLineEdit provides an editable one line text input box:
self.input = QLineEdit()
self.input.setPlaceholderText("Enter your name")
Useful methods:
setText()/text()– Set/get textsetEchoMode()– Normal, password, hide inputsetClearButtonEnabled()– Show clear buttonsetMaxLength()– Limit input length
We can get notified on text change by connecting to its textChanged signal.
Displaying Text with QLabel
The QLabel widget displays read-only text and images:
label = QLabel("Hello World!")
Use setText() to change the display text. We can style the text using the setStyleSheet() method:
label.setStyleSheet("font-size: 25px; font-weight: bold;")
Some parameters that can be styled: font family/size/weight/style, foreground/background color, margins/padding, borders etc.
Laying Out UI Elements
PyQt5 has various layout classes to handle positioning of widgets in the window. Some common ones are:
QHBoxLayoutandQVBoxLayout: Horizontal and vertical box layoutsQGridLayout: Grid based layout with rows and columns
For example, to lay out a label and input box horizontally:
hbox = QHBoxLayout()
hbox.addWidget(label)
hbox.addWidget(input)
self.setLayout(hbox)
And to align them vertically instead:
vbox = QVBoxLayout()
vbox.addWidget(label)
vbox.addWidget(input)
self.setLayout(vbox)
Layouts greatly simplify handling of sizes and positions across different window sizes.
PyQt5 Architecture
Before going deeper, let‘s understand a bit about how PyQt5 works under the hood.
PyQt5 is a set of Python bindings for Qt – a popular C++ GUI framework. The architecture looks like this:

The key components are:
Qt Core – Base non-GUI classes used by other modules like network access, JSON handling, threading etc.
Qt GUI Modules – Widgets, graphics drawing etc.
Qt Bindings – auto-generated bindings to expose Qt APIs to other languages like Python.
So PyQt5 gives us a generated Python interface allowing Python code to leverage all Qt functionality.
The key benefits PyQt5 provides over raw Qt usage are:
- Don‘t need to write C++ code
- Automatic type conversions
- Support for Python native types
- Integrates well with other Python packages
Building and Distributing PyQt5 Apps
When our application coding is complete, we need to package it into an executable file before giving to end users. Here are some options:
PyInstaller
PyInstaller bundles Python apps into stand-alone executables easily.
pip install pyinstaller
pyinstaller myscript.spec
CX Freeze
Converts Python scripts into executables in a very customizable way.
fman build system
fman‘s build system focuses on reliability and stability. It integrates well with PyQt5.
The executable can then be distributed on Linux, Mac and Windows platforms.
Designing UI Forms with Qt Designer
While we can create simple UIs directly in code, Qt Designer is invaluable for building complex interfaces.
Steps to use Qt Designer:
- Design UI visually by dragging and arranging widgets
- Save design as
.uifile - Convert to
.pyfile - Import generated file
For example:
pyuic5 myform.ui -o myform.py
from myform import Ui_MyForm
class MyForm(QWidget):
def __init__(self):
super().__init__()
self.ui = Ui_MyForm()
self.ui.setupUi(self)
Now all UI elements created in designer are available in self.ui.
This separates presentation layer (in .ui file) from logic layer (in Python code).

In addition to dialogs and main window forms, Qt Designer also allows visually building:
- Custom widgets that can be reused
- Toolbars, dock widgets
- Model-View based forms
This accelerates development by letting you focus on behavior rather than presentation.
Databases with PyQt5
PyQt5 provides good integration with the SQLite database which is serverless. This allows building applications that use local data without needing to setup a separate database server process.
Here is an example showing a database enabled application with PyQt5 that displays and graphs sensor data:
import sqlite3
import datetime
from PyQt5.QtCharts import QtCharts
from PyQt5.QtWidgets import QApplication, QMainWindow
# Subclass QMainWindow to customize main application window
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.database = sqlite3.connect("sensors.db")
...
# Read data from database
results = self.database.execute("SELECT * FROM readings")
# Plot data read from database
for row in results:
self.plot.add_datapoint(row[0], row[1])
...
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
The data and structure can be initialized easily through SQL queries. This helps avoid having to setup a full-fledged client-server style database architecture.
Data Visualization
For plotting and visualizing data, PyQt5 integrates well with both Matplotlib and Qt‘s own charting library – Qt Charts.
Matplotlib
Matplotlib can render plots, histograms, power spectra, bar charts and many other types of data graphics.

The FigureCanvas widget can be used to embed matplotlib plots into PyQt5 windows.
Qt Charts
Qt Charts provides easy APIs for some common chart types like line, spline, area, bar, pie and scatter plots.
The QtCharts module contains charting widgets that can be added to PyQt5 applications directly.
So with PyQt5, developers have the flexibility to use either Matplotlib or Qt Charts depending on their specific visualization needs.
Multithreading with PyQt5
Similar to the original Qt framework, PyQt5 provides strong support for multithreaded applications. Multithreading allows long running tasks to be moved to background threads so they do not block the main UI.
Here is an example:
import threading
import time
from PyQt5.QtCore import QThread, pyqtSignal
class LongTask(QThread):
task_finished = pyqtSignal(str)
def run(self):
time.sleep(10) # Simulate long task
self.task_finished.emit("Task completed!")
class MainWindow(QMainWindow):
def __init__(self):
...
thread = LongTask()
thread.task_finished.connect(self.onTaskFinished)
thread.start()
def onTaskFinished(self, message):
print("Completed background task:", message)
The key points are:
- Subclass
QThreadand override itsrun()method for background task logic - Create thread instance and call
start()to run - Communicate back to main thread using signals
This keeps the GUI responsive even with long TCP operations, blocking IO calls etc.
Packaging PyQt5 Apps
Once application coding is complete, we need to package the Python code into an executable file for distribution to end users.
Here are some handy options for converting .py to .exe:
| Tool | Description |
|---|---|
| PyInstaller | Bundle app and dependencies into one .exe file |
| CX Freeze | Customizable exe builder with many options |
| fbs pyinstaller | Tailored specifically for freezing PyQt5 apps |
| Briefcase | Builds mobile and desktop apps from Python code |
For web deployment, the app code can be compiled to JavaScript using tools like PyScript, Pyodide and Transcrypt.
Once packaged, the executables can run standalone on Windows, Mac and Linux without needing Python preinstalled.
Deploying PyQt5 Applications
The major platforms supported for deployment are:
Windows
Windows .exe generated by tools like PyInstaller runs without any other dependencies needed.
MacOS
Mac .app bundles can be generated. Or user installs Python + PyQt5 on their system.
Linux
Providing self-contained AppImages or .deb/.rpm packages avoids external dependencies.
Mobile
Buildozer and Kivy can compile to Android APKs. For iOS, Qt framework should be used instead of PyQt5.
So there are good options available for deploying PyQt5 applications across desktop, server and mobile platforms.
Conclusion
In this guide, we looked at:
- Getting started with PyQt5
- Using basic widgets like buttons, input boxes and labels
- Layout managers for aligning UI elements
- Signals and slots for communication between objects in PyQt5
- Architecture of how PyQt5 interfaces with Qt
- Options for building installable executables for distribution
- Using Qt Designer visual editor to design dialogs and window forms
- SQLite database integration example
- Data visualization integrating matplotlib and Qt charts
- Multithreading techniques to keep UI responsive
- Packaging options for Linux, Mac and Windows
There is still too much about PyQt5 we didn‘t cover – 3D graphics, multimedia, QtQuick, SVG, OpenGL integration, web integration, accessibility and internationalization.
I hope this overview gives you a good starting point for leveraging PyQt5 to build modern, scalable cross-platform desktop applications with Python! Let me know if you have any other questions.


