Qt for Python

General Introduction

For internal and external distribution

Naming

Qt for Python is the global name of the project.

The story of PySide

2008

Qt4
Development
(PySide)

2016

Back
to the
Qt Project

2015

Qt5
Port
(PySide2)

2018

Released
(Qt for Python)

Release information

  • Qt for Python (Qt 5.11) - Technical Preview
  • Qt for Python (Qt 5.12) - Official Release
  • Releases follow the Qt releases
    • Qt5 latest is 5.15.2 OSS and 5.15.5 Commercial LTS
    • Qt6 latest is 6.1.2

(Slide updated on 05.07.2021)

Python Compatibility

  • Python 2.7 (deprecated for Qt 6)
  • Python 3.6 or greater is required

License (1/2)

  • LGPLv3/GPLv3 for OpenSource users
    • The tools we included are GPLv3
      pyside6-uic, pyside6-rcc,
      pyside6-designer
    • shiboken generator is GPLv3
    • Qt libraries licenses depends on the module
      (*.so, *.dll, *.dylib)
    • everything else is LGPLv3

License (2/2)

  • Commercial included in the
    "Qt for Application Development".
  • Commercial included in the
    "Qt Device Creation".
    • Only 3 modules from M2M Protocols
      (QtOpcUa, QtMqtt, QtCoAp)

Setup πŸ”¨

Installation

  • Installing Qt doesn't include Qt for Python
    • Not listed on the Qt Installer
  • Qt for Python is distributed via Python Packages (wheels)
  • OSS and Commercial installations are different.

How to install (Open Source)

What is installed?


     β–ͺ️PySide6
      β”œβ”€β”€ Qt modules              βœ…
      β”œβ”€β”€ pyside6-designer        βœ…
      β”œβ”€β”€ pyside6-rcc             βœ…
      └── pyside6-uic             βœ…
     β–ͺ️Shiboken6 (module)
      └── shiboken6               βœ…
     β–ͺ️Shiboken6_Generator (exe)
      └── shiboken6               ❌
    

Installing shiboken_generator

The main issue for not having it public is the dependency with libclang.

Installing Shiboken Generator

the simple way


    pip install \
        --index-url=http://download.qt.io/official_releases/QtForPython/ \
        --trusted-host download.qt.io \
        shiboken6 pyside6 shiboken6_generator
    

But one needs to:

  • Set CLANG_INSTALL_DIR to the libclang directory
  • Add to PATH a Qt bin path with the same version
  • Add to LD_LIBRARY_PATH the Qt lib path with the same version

Installing Shiboken Generator

the hard way?

  • Set CLANG_INSTALL_DIR to the libclang directory

    python setup.py install
    # there are many other options!
    
doc.qt.io/qtforpython/gettingstarted.html

How to install (Commercial)

  • Download packages (.whl files) from account.qt.io
  • Installing them on a terminal:
  • 
                pip install shiboken6-xxxx.whl pyside6-xxxx.whl
                

(xxxx contains information about architecture, OS and the PySide, Qt, and Python versions)

What is installed?


     β–ͺ️PySide6
      β”œβ”€β”€ Qt modules              βœ…
      β”œβ”€β”€ Qt M2M Protocols        βœ…πŸ†•
      β”œβ”€β”€ pyside6-designer        βœ…
      β”œβ”€β”€ pyside6-rcc             βœ…
      β”œβ”€β”€ pyside6-uic             βœ…
      └── shiboken-wizard         βœ…πŸ†•
     β–ͺ️Shiboken6 (module)
      └── shiboken6               βœ…
     β–ͺ️Shiboken6_Generator (exe)
      └── shiboken6               ❌
    

Language differences

Python and C++

C++

  • General purpose and
    Multi-paradigm

C++

  • Statically typed
    
                    int a = 1;
                    float b = 4.3;
                    string c = "hello";

C++

  • Compiled
    
                $ g++ main.cpp -o main
                $ ./main

C++

  • Provides low-level memory manipulation
    
                QObject *obj = new QObject(...);
                delete obj;

C++

  • Code readability
    
                #include <iostream>
                using namespace std;
    
                int main(int argc, char *argv[]) {
                    cout << "Hello World" << endl;
                }

Qt Example

QMainWindow with a QPushButton
C++

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H

        #include 
        #include 

        class MainWindow : public QMainWindow
        {
            Q_OBJECT
            public:
                MainWindow(QWidget *parent = nullptr);
            private slots:
                void handleButton();
            private:
                QPushButton *m_button;
        };

        #endif // MAINWINDOW_H

        #include "mainwindow.h"

        MainWindow::MainWindow(QWidget *parent)
           : QMainWindow(parent)
        {
            m_button = new QPushButton("My Button", this);
            connect(m_button, SIGNAL(clicked()), this, SLOT(handleButton()));
        }

        void MainWindow::handleButton()
        {
            m_button->setText("Ready");
        }

        #include 
        #include "mainwindow.h"

        int main(int argc, char *argv[])
        {
            QApplication app(argc, argv);
            MainWindow mainWindow;
            mainWindow.show();
            return app.exec(d);
        }
Python

        import sys
        from pyside6.QtWidgets import QApplication, QMainWindow, QPushButton

        class MainWindow(QMainWindow):
            def __init__(self, parent=None):
                QMainWindow.__init__(self, parent)
                self.button = QPushButton("My Button", self)
                self.button.clicked.connect(self.handleButton)

            def handleButton(self):
                self.button.setText("Ready")

        if __name__ == "__main__":
            app = QApplication([])
            mainWindow = MainWindow()
            mainWindow.show()
            sys.exit(app.exec_())

Qt Compatibility

Checked on 5.15

(For Qt6, following available modules)

Qt Essentials

Core GUI Multimedia Multimedia Widgets
Network QML Quick Quick Controls
Quick Dialogs Quick Layouts Quick Test SQL
Test Widgets

Some modules could be incomplete, please see wiki.qt.io/Qt_for_Python_Missing_Bindings for more information.

Qt Add-Ons

Active Qt 3D Android Extras Bluetooth Concurrent
D-Bus Gamepad Graphical Effects Help Image Formats
Location Mac Extras NFC OpenGL Platform Headers
Positioning Print Support Purchasing Quick Controls1 Quick Extras
Quick Widgets Remote Objects Script SCXML Script Tools
Sensors Serial Bus Serial Port Speech SVG
UI Tools WebChannel WebEngine WebSockets WebView
Windows Extras X11 Extras XML XML Patterns Wayland Compositor
Charts Data Visualization Network Authorization Virtual Keyboard Quick WebGL

Some modules could be incomplete, please see wiki.qt.io/Qt_for_Python_Missing_Bindings for more information.

Value-Add Modules

Qt Automotive Suite Qt M2M Protocols (1) Qt for Device Creation Qt for MCU (2)

(1) KNX is not included.

(2) Python doesn't have official support on Microcontrollers. Micro/Circuit Python are subsets of Python, and we don't support them.

Platforms

Windows Linux
macOS Android and iOS (1)
WebAssembly (1) Embedded (2)

  • (1) Python doesn't have official support for Android, iOS, nor WebAssembly
  • (2) ARM based Linux distributions (Raspberry OS, ArchLinuxARM) provide PySide as a system package.

Binding generation

Shiboken

Generation process

Shiboken
ζ­»ζŸε‰£

doc.qt.io/qtforpython/shiboken6

Shiboken

Module

import shiboken6

  • Helper functions
    • isValid(obj)
    • getCppPointer(obj)
    • isOwnedByPython(obj)
    • VoidPtr class

Qt Creator

Qt Creator compatibility

Qt Creator templates

  • Empty application,
  • Basic Widget application,
  • Basic Widget application (.ui file), from 4.12,
  • QtQuick application (QML), from 4.12.

Qt Creator functionality


Can
  • Create new projects,
  • Syntax highlight,
  • Code completion,
  • Add/remove files,
  • Execute applications,
  • Select Python interpreter.
Cannot
  • Generate Python code from ui and qrc files,
  • Install new Python modules,
  • Remote debugging.

What's there besides the Qt API?

Added value

Qt's a C++ framework, and that might be confusing.
  • camelCase API is not a Python standard
  • The usage of setters/getters is not common, in favor of writable properties
  • Qt has data structures to improve C++'s developers life, but Python too.

The __feature__ option


      # Common Qt structure
      # - Using setter/getter
      # - No writable properties

      table = QTableWidget()
      table.setColumnCount(2)

      button = QPushButton("Add")
      button.setEnabled(False)

      layout = QVBoxLayout()
      layout.addWidget(table)
      layout.addWidget(button)
      

Python compatibility

  • Usage Python native structures instead of QVariant
  • Sequences (Python Lists, Tuples, etc) instead of Qt Sequences
  • Compatibility with pathlib objects (6.2)
  • Usage of numpy.array instead of numerical arrays

Shiboken Wizard

Easy graphical way to generate Python bindings from a C++ project.

Shiboken Wizard

Overview video

Common Use Cases

Pure Python Applications

Custom Python Bindings (without Qt)

Generating Python bindings
from a C++ library.

  • Library files:
    • CMakeLists.txt
    • icecream.cpp
    • icecream.h
    • truck.cpp
    • truck.h
  • Shiboken files:
    • bindings.h (right top)
    • bindings.xml (right bottom)

β˜… Check the samplebinding example


        #ifndef BINDINGS_H
        #define BINDINGS_H

        #include "icecream.h"
        #include "truck.h"

        #endif // BINDINGS_H
<typesystem package="Universe"> <primitive-type name="bool"/> <primitive-type name="std::string"/> <object-type name="Icecream"> <modify-function signature="clone()"> <modify-argument index="0"> <define-ownership owner="c++"/> </modify-argument> </modify-function> </object-type> <value-type name="Truck"> <!-- Same ownership caveat applies here. --> <modify-function signature="addIcecreamFlavor(Icecream*)"> <modify-argument index="1"> <define-ownership owner="c++"/> </modify-argument> </modify-function> </value-type> </typesystem>

Custom Python Bindings (with Qt)

Simple typesystem

<typesystem package="wiggly"> <load-typesystem name="typesystem_widgets.xml" generate="no"/> <object-type name="WigglyWidget"/> </typesystem>

Python usage

from wiggly import WigglyWidget as WigglyWidgetCPP
from wigglywidget import WigglyWidget as WigglyWidgetPY

# ...
wiggly_widget_py = WigglyWidgetPY(self)
wiggly_widget_cpp = WigglyWidgetCPP(self)
# ...
layout.addWidget(wiggly_widget_py)
layout.addWidget(wiggly_widget_cpp)
      

β˜… Check the widgetbinding example


  • Top: Widget written in Python
  • Bottom: Widget written in C++ (exposed to Python)

Hybrid Applications (Python and C++)

Embedded Python into a Qt/C++ application

The Text editor interprets Python code to access the Qt/C++ application to modify it.

β˜… Check the scriptableapplication example

Final remarks

Future steps

  • Documentation,
  • Continuing improving C++/Python interaction,
  • Tooling around Shiboken and PySide,
  • Ready-to-use widgets for other Python modules,
  • Research on embedded systems.

For more details, refer to our vision blog post
qt.io/blog/2019/08/19/technical-vision-qt-python

Where to start

Webinars

Communication channels

More platforms at wiki.qt.io/Qt_for_Python#Community

Qt for Python

General Introduction

Dr. CristiΓ‘n Maureira-Fredes
R&D Manager @ TQtC