Search by Tags

How to build a GUI with Qt for Python and TorizonCore

 

Article updated at 05 Jun 2020
Subscribe for this article updates

Introduction

Qt for Python offers the official Python bindings for Qt (PySide2) to build powerful Graphical User Interfaces (GUI). In this article, we will explain the Qt for Python usage and how you can use it in TorizonCore.

This article complies to the Typographic Conventions for Torizon Documentation

Prerequisites

Using Qt for Python - PySide2

Qt for Python project provides pySide2 to implement Qt applications using Python. pySide2 allows access to the complete Qt 5.12+ framework.

A pySide2/QML application requires at least two files:

  • QML file describing the UI
  • Python file loading the QML.

In this article, we will demonstrate a basic Qt for Python project created from scratch. The source code of the example is available on the project's GitHub page.

The QML file

QML is a declarative language to describe the user interface.

The QML file of the sample project describes the existing elements in the UI. For example, to create a button, the following code snippet is used:

usr_interface.qml
Button {
    id: button
    x: 62
    y: 40
    width: 94
    height: 37
    text: qsTr("Temp/Hum")
    clip: false
    checkable: false
    opacity: 1
    onClicked: pythonObj.generateEvent()
}

The Python script

In addition to the QML file, it is necessary a Python script to load the QML. In the main Python file of the project, the main function handles the QML file loading.

show_readings.py
if __name__ == '__main__':
    appObj = QGuiApplication(sys.argv)
    engineObj = QQmlApplicationEngine()
 
    eventObj = EventGenerator()
    engineObj.rootContext().setContextProperty("pythonObj", eventObj)
 
    # Load the QML file with the description of the GUI
    qmlFile = join(dirname(__file__), 'usr_interface.qml')
    engineObj.load(QUrl(qmlFile))
 
    if not engineObj.rootObjects():
        sys.exit(-1)    
 
    sys.exit(appObj.exec_())

The Dockerfile

See the example Dockerfile on Github for this project. Remember to set the IMAGE_ARCH and APPNAME variables accordingly to your needs. Set IMAGE_ARCH=arm32v7 for 32-bits SoC (i.MX6, i.MX7) or IMAGE_ARCH=arm64v8 for 64-bits SoC (i.MX8).

Please note that the pyside2 and QML requires the following Debian packages:

Dockerfile
RUN apt-get update && apt-get install -y --no-install-recommends \
    python3 \
    qml-module-qtquick2 \
    qml-module-qtquick-controls \
    qml-module-qtquick-controls2 \
    qml-module-qtquick-dialogs \
    python3-pyside2.qtcore \
    python3-pyside2.qtquick \
    python3-pyside2.qtwidgets \
    python3-pyside2.qtgui \
    python3-pyside2.qtqml \
    python3-pyside2.qtnetwork \
    && rm -rf /var/lib/apt/lists/*

Note: you may need to add or remove dependencies based on your project's needs. There are several other qml-module- and python3-pyside2. packages available.

Running the Sample code

See the Torizon Samples Github Page for an example written in Python, reading temperature and humidity from i2c based sht3x sensor and showing it on the GUI developed using QML.


  • Sample Qt Application

    Sample Qt Application

Deployment From the Command-line

1 - In your development host machine, git clone the Torizon Samples repository:

$ git clone https://github.com/toradex/torizon-samples.git

2 - Change to the torizon-samples/python-qml directory. Build the container image.

$ cd torizon-samples/python-qml
$ docker build . -t <your-dockehub-username>/python-qml

3- Push the image to your Dockerhub account:

$ docker push <your-dockehub-username>/python-qml

4- In your board's terminal, pull the Docker container image:

# docker pull <your-dockehub-username>/python-qml

5- The image built with this Dockerfile requires the Qt Wayland container. Therefore, we start the Weston container as the graphics server, as explained on the Qt Debian Container for Torizon, before the application. Select your SoM from the tabs below and follow the instructions:

Start weston using the torizon/arm32v7-debian-weston:buster container image:

# docker run -d --rm --name=weston --net=host --cap-add CAP_SYS_TTY_CONFIG \
             -v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
             --device-cgroup-rule='c 4:* rmw' --device-cgroup-rule='c 13:* rmw'  --device-cgroup-rule='c 226:* rmw'\
              torizon/arm32v7-debian-weston:buster --developer weston-launch --tty=/dev/tty7 --user=torizon

Start weston using the torizon/arm32v7-debian-weston:buster container image:

# docker run -d --rm --name=weston --net=host --cap-add CAP_SYS_TTY_CONFIG \
             -v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
             --device-cgroup-rule='c 4:* rmw'  --device-cgroup-rule='c 13:* rmw' --device-cgroup-rule='c 226:* rmw' \
              torizon/arm32v7-debian-weston:buster --developer weston-launch --tty=/dev/tty7 --user=torizon -- --use-pixman

Start weston using the torizon/arm64v8-debian-weston-vivante:buster container image:

Attention: Please, note that by executing the following line you are accepting the terms and conditions of the NXP's End-User License Agreement (EULA)

# docker run -e ACCEPT_FSL_EULA=1 -d --rm --name=weston --net=host --cap-add CAP_SYS_TTY_CONFIG \
             -v /dev:/dev -v /tmp:/tmp -v /run/udev/:/run/udev/ \
             --device-cgroup-rule='c 4:* rmw'  --device-cgroup-rule='c 13:* rmw' --device-cgroup-rule='c 199:* rmw' --device-cgroup-rule='c 226:* rmw' \
              torizon/arm64v8-debian-weston-vivante:buster --developer weston-launch --tty=/dev/tty7 --user=torizon

6- Run the sample image:

# docker run --rm -it -v /tmp:/tmp \
-v /dev/dri:/dev/dri --device-cgroup-rule='c 226:* rmw' \
<your-dockehub-username>/python-qml

A window should pop up with a button and two text fields.

Deployment using the Visual Studio Code Extension

The same project can also be built/deployed/debugged/released through VScode using the extension for Python.

1 - Git clone the Torizon Samples repository:

$ git clone https://github.com/toradex/torizon-samples.git

2 - Create a new Python project on VS Code. See Python Development and Debugging on Torizon Using Visual Studio Code article for detailed instructions on how to start and build a new Python project with Torizon.

Warning: Select python3 arm32v7 qt or python3 arm64v8 qt as the base image, depending on the target module.

3 - Add all the files from the folder python-qml/python-qml/app to your VS Code project. You can use the mouse to add and drop these files to your project.

4 - Copy the content from the show_readings.py file to main.py, overwriting the original content of the main.py file. After this, you can remove the show_readings.py file.

5 - On the appconfig_0 folder of the project, create a new file on the VS Code, with the name docker-compose.yml. This Docker Compose file defines the containers to start the TorizonCore Debian With Weston Wayland Compositor Image before to display the Qt application. See the image's .yml sample file for arm64v8 or .yml sample file for arm32v7 as reference.

Note: Only the Weston service is needed to be copied to your .yml file.

Warning: for iMX8, also add the following lines to the Weston service to accept NXP's EULA required to run Vivante's graphic drivers

docker-compose.yml
environment:
- ACCEPT_FSL_EULA=1

6 - Open the Torizon Configurations view, To do that, press F1 in Visual Studio Code command bar and then type "Torizon/Python: Focus on Configurations View"

7 - On the dockercomposefile property, type docker-compose.yml.

8 - Press F5 to build and run your application.