Creating desktop applications with Python using PyQt5

Introduction

PyQt5 is a Python package that provides a wrapper for accessing the Qt framework libraries. Qt is a cross platform widget toolkit that allows creating graphical user interfaces. It supports Windows, Android, Linux and Mac. Several options exist for developing GUI applications using Python. For example Pyside, TKinter, PyGTK and Kivy are Python packages for creating GUI applications

The obvious benefit of desktop applications is that they allow the data to remain on the local computer. Also the desktop application is always available since it does not depend on internet connectivity. The drawback of desktop applications is that they are not as easy to access as Web based applications. For instance a desktop application needs to be installed on each computer where it is to run.

Installation

Python virtual environments are often used during development. The benefit of using virtual environments is that they allow packages to be installed independently of other virtual environments or the system wide packages. virtualenv is a virtual environment for Python. To create a new virtual environment using virtualenv, the following command is run:

python3 -m virtualenv path-to-project

will create a folder with standard Python libraries and binaries. This folder works as an isolatedenvironment within which Python applications can be developed. Once a virtual environment has been created, it needs to activated using the command:

source bin/activate

Packages can be installed in the virtual environment using the pip package manager. To install the PyQt5 package, we need to run the command:

pip install PyQt5

To test if the PyQt5 package has been successfully installed, enter the command:

import PyQt5

from the Python shell. If the command does not give errors, then the PyQt5 has been successfully installed

Qt 5 Tools is a package that provides tools for the Qt5 framework. It includes the Qt5 Desginer which is a graphical designer for Qt5 applications. The Qt5 tools package may be installed with the command:

pip install qt5-tools

Creating PyQt5 applications

Python GUI applications are run in the same way as command line applications. The main difference is that instead of output being shown on the console, a graphical window pops up. The main steps in writing a PyQt5 application are:

  • Import the QtWidgets class using:
from PyQt5 import QtWidgets
  • Create an instance of the QMainWindow class. Command line arguments are passed to the constructor.
app = QtWidgets.QApplication(sys.argv)
  • Create an instance of the QMainWindow class. This is the actual user interface class.
MainWindow = QtWidgets.QMainWindow()
  • Create an instance of the Ui_MainWindow class using:
ui = Ui_MainWindow()

This class is used to setup the user interface class created in the previous step. This class is generated by the pyuic5 tool. The pyuic5 tool is used to generate python code from the user interface class created by the Qt Designer. The following code is used to setup the MainWindow class:

ui.setupUi(MainWindow)
  • The next step is to create an instance of your own class. As an example the class can be named Ui_Manager. This class is used to setup event handlers for the graphical components. The constructor of this class may take the ui object as parameter.
  • The next step is to display the window using: MainWindow.show(). This method blocks until the user closes the application.
  • The final step is to call: sys.exit(app.exec_()). This will end the application

The GUI related code is usually auto generated using the Qt Desginer and pyuic5. We need to keep our custom code such as event handling code separate from the auto generated GUI code. Otherwise the custom code can get overwritten. The benefit of this approach is that it separates the users custom graphics code from the auto generated code. The following code shows the “main” function of a typical PyQt5 application:

if __name__ == "__main__":    
    app        = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui         = Ui_MainWindow()
    ui.setupUi(MainWindow)

    ui_manager = Ui_Manager()
    ui_manager.initialize_ui(ui);
    MainWindow.show()
    sys.exit(app.exec_())

Using the Qt Designer

The Qt Designer allows generating user interface for Qt5 applications. It allows user interfaces to be created by dragging and dropping widgets. It supports several widgets such as ComboBoxes, Lists, Tables, Buttons, Labels and more. It supports four types of layouts which are Horizontal Layout, Vertical Layout, Grid Layout and Form Layout. These layouts allow widgets to be arranged correctly.

Each user interface created in the Qt Designer is saved in XML format as a single file with .ui extension. Each .ui file need to be converted to Python code. This can be done using the pyuic5 tool. For example the following command creates a Python file from a .ui file:

pyuic5 ui-file.ui -o ui-file.py

The generated Python file can be run using python3 ui-file.py. This will run the GUI application. The application should look exactly like the preview in the Qt Designer.

The PyQt5 framework provides classes in Python for creating desktop applications. It provides classes for widgets. For example the QApplication class implements the main window class. Classes such as QLabel and QPushButton implement labels and buttons.

Generating executable files using pyqtdeploy

pyqtdeploy is a tool that allows deploying PyQt applications. It supports deploying applications to desktop platforms and mobile platforms. It supports Linux, Windows, MacOs and Android. pyqtdeploy creates a standalone binary file that can be run on the target platform.

pyqtdeploy can be installed as a Python package using the command:

pip install pyqtdeploy

It requires PyQt5 and Python 3.5 and later. A useful way to learn about pyqtdeploy is to deploy the demo application that is packaged with pyqtdeploy. The demo application is a simple application written using PyQt5 and Python. The documentation for the demo application describes how to build the application on the target platform.

Generating a standalone binary file using pyqtdeploy requires the following steps:

  • Identify the PyQt modules and other third party components that are required by the application. These components are specified in the sysroot.json file. The sysroot.json file that is provided with the demo application is a good starting point.

The systemroot contains the Python libraries and third part components required by the application. The document Building a System Root Directory describes how to build a sysroot. Building a sysroot can take several hours depending on the components selected. The system root is then built using the command:

pyqtdeploy-sysroot  --sysroot sysroot-linux-64/ --source-dir lib --verbose  sysroot.json

The pyqtdeploy-sysroot command is part of the pyqtdeploy package.

Building a sysroot causes the components specified in sysroot.json to be compiled. Qt5, Python interpreter, Sip and PyQt5 are core components and need to listed in sysroot.json. SSL and Zlib are optional components.

Compiling Qt5 requires certain packages. The article Qt for X11 Requirements describes the dependency packages that are required for building Qt5 from source. For example on Ubuntu the dependencies may be installed with the command:

sudo apt-get build-dep qt5-default

Note that this command requires source entries in the /etc/apt/sources.list file.

  • The next step is to create a project file that identifies the application source code and all the components used by the application. The project file has a .pdy file extension. It can be created using the pyqtdeploy command. This command opens a graphical application that allows generating the project file.

For example the command: pyqtdeploy pyqt-demo.pdy allows editing project file for the demo application. The document Creating a pyqtdeploy Project describes how to create a pyqtdeploy project.

  • The next step is to freeze the Python modules and generate a .pro file. This can be done using the command:
pyqtdeploy-build --sysroot sysroot-linux-64/  --verbose pyqt-demo.pdy

The article Building the Application describes how to do generate the .pro file.

  • The next step is to generate the MakeFile using the qmake command. This can be done using the command:
[path-to-qmake] pyqt-demo.pro

This command should be run from the target build directory which was generated during the previous step. The path-to-qmake is the absolute path to the qmake binary file within the sysroot. This is usually sysroot-linux-64/Qt/bin/qmake. Once the MakeFile has been generated, the next step is to generate the executable file using the command: make.

Conclusion

In this article I have described my experience with creating graphical applications using the PyQt5 framework and deploying the graphical applications using pyqtdeploy.

Published 10 Aug 2021

Tutorials about Web Development, Server Management, Computer Science and more