A tool to create cross-platform apps using only Python and the Qt Framework.
PyQt-CroM demonstrates the capabilities of pyqtdeploy and optimises its use.
PyQt-CroM is mainly aimed at the following groups.
There are various reasons to create yet another cross-platform app generation tool (especially based on Python and the Qt framework):
Javascript is the current leading language for cross-platform app development frameworks (e.g. React Native, Nodejs, Ionic). However, Javascript is harder to pick up and learn for beginners than Python
. Furthermore, Python comes with built-in modules and an extensive list of libraries, whereas Javascript only comes with a few powerful libraries, which makes Javascript still less handy and less flexible for intermediate and expert developers
.
Flutter is gaining traction in the cross-platform ecosystem, as it is fast, flexible and allows native feature access. Its base language is Dart language, which is easy to learn, fast, performant and documented, but Dart suffers from a lack of online resources and community support
(as it is fairly recent). On the contrary, Python benefits from countless useful online resources, as well as a large and active community.
No-code or low-code platforms (e.g. Bubble) are a great option for beginners as they help them prototype quickly, but no-code platforms are very limited in functionalities sought after by intermediate and expert developers
. Some platforms (e.g. FlutterFlow) enable the use of code to extend existing capabilities, but this increases the the level of access requirements for beginners. Python is a great competitor to low-code platforms as it is accessible to beginners, and is also a great competitor to more advanced platforms, as it boasts a large range of libraries, making it easy to customise features and create advanced functionalities.
Kivy and BeeWare are the most famous cross-platform app development frameworks based on Python. Even though Kivy is more focused on non-native user interface and BeeWare is more focused on native feel, Kivy and BeeWare can't provide native and non-native feel in one framework simultaneously. Furthermore, they both lack community support and good documentation
. On the contrary, PyQt relies relies on the Qt framework which is the leader in GUI apps (thanks to an active community) and allows to develop apps with a native feel (QtWidgets) or a more custom and standardised look (QtQuick) according to Qt framework comparison.
Tkinter relies on Python and the code is stable, however the user interface in Tkinter is not appealing and the code is hard to debug
. On the contrary, PyQt makes Qt components directly accessible from the Python language, which makes it easy to organise, customise and debug code (thanks to recognised Qt expertise).
PySide is developed by Qt, but surprisingly requires a lot of setup and various tools to convert from a script to a mobile app for instance, as expressed by Qt itself on Qt website. Even though pyqtdeploy also requires a lot of setup to convert a PyQt script into a cross-platform app, the process is robust and reliable.
:heavy_check_mark: The tool pyqtdeploy is still not perfect, but the limitations are non-critical for the target audience:
The aforementioned limitations constitute obstacles that can be tackled by PyQt-CroM.
:mag: This tutorial guides you through the process of generating a cross-platform app from a simple PyQt5 demo app.
:trophy: By the end of the tutorial, you will be able to launch the simple PyQt5 demo app from your Android phone:
Specs of Linux machine used:
Ubuntu 22.04
(EOL April 2032) with around 40-50GB available (to install the dependencies)Python 3.10.12
(EOL October 2026) pre-installed on Ubuntu 22:bulb: _Refer to Virtual Machine Setup if you don't have a Linux OS available on your machine._
Specs of target OS:
Android 9.0
as targeted Android features (default)Android 9.0
as minimum Android version to run the app (default)Use the HTTPS method if you don't have a Github account:
cd $HOME/Documents \
&& git clone https://github.com/achille-martin/pyqt-crom.git
Use the SSH method if you have a Github account (and SSH key setup):
cd $HOME/Documents \
&& git clone git@github.com:achille-martin/pyqt-crom
:warning: _We will use PYQT_CROM_DIR
as the variable containing the path to the main repo._
Add the variable to your .bashrc
with:
printf "%s\n" \
"" \
"# Environment variable for PyQt-CroM path" \
"export PYQT_CROM_DIR=$HOME/Documents/pyqt-crom" \
"" \
>> $HOME/.bashrc \
&& source $HOME/.bashrc
sudo apt-get update \
&& sudo apt-get install python3-pip \
&& python3 -m pip install --upgrade pip \
&& sudo apt-get install python3-virtualenv \
&& cd $PYQT_CROM_DIR \
&& mkdir -p venv \
&& cd venv \
&& virtualenv pyqt-crom-venv -p python3 \
&& cd ..
source $PYQT_CROM_DIR/venv/pyqt-crom-venv/bin/activate
:bulb: To exit the virtual environment, type in your terminal deactivate
.
Make sure that pip3 (pip for python3) has been upgraded to v23.3.2 (or later) in the virtual environment with:
pip3 --version
If pip3 needs to be upgraded, run the command:
pip3 install --upgrade pip
Install the pip packages in the virtual environment with:
cd $PYQT_CROM_DIR \
&& pip3 cache purge \
&& pip3 install -r requirements.txt
:bulb: You can confirm the installed pip packages with pip3 list --local
.
cd $PYQT_CROM_DIR/examples/demo/demo_project/demo_pkg \
&& python3 demo_app.py
The PyQt5 demo app will start and you can confirm that it is displayed properly on your machine:
Download the sources with:
cd $PYQT_CROM_DIR/utils/resources \
&& chmod +x download_sources.sh \
&& ./download_sources.sh
:bulb: _You can confirm that the list of packages required matches with the versions from $PYQT_CROM_DIR/examples/demo/demo_project/sysroot.toml
._
Install zlib on Ubuntu with:
sudo apt install zlib1g-dev
Zlib is required by the pyqtdeploy project $PYQT_CROM_DIR/examples/demo/demo_project/config.pdt
to correctly identify the dependencies from the $PYQT_CROM_DIR/examples/demo/demo_project/sysroot.toml
.
:bulb: Sysroot setup tips can be obtained from Riverbank website.
Install stable java JDK 11 available for your Ubuntu distribution and tested with Gradle:
sudo apt install openjdk-11-jdk openjdk-11-jre
Set the default java and javac version to 11 using:
sudo update-alternatives --config java \
&& sudo update-alternatives --config javac
:hand: Confirm the version with java -version && javac -version
which should be v11.0.21
.
Download Android Studio version 2023.1.1.26
with:
sudo apt-get install wget \
&& cd $HOME/Downloads \
&& wget https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2023.1.1.26/android-studio-2023.1.1.26-linux.tar.gz
Move the contents of the downloaded tar.gz
to your $HOME
directory using:
cd $HOME/Downloads \
&& tar -xvf android-studio-2023.1.1.26-linux.tar.gz \
&& mv android-studio $HOME
Start the installation with:
cd $HOME/android-studio/bin \
&& ./studio.sh
:bulb: Tip: if there is an issue with android studio start, use sudo ./studio.sh
.
The Android Studio installer will start:
$HOME/Android/Sdk
:hand: Make sure that the default SDK has been installed in $HOME/Android/Sdk
and that $HOME/Android/Sdk/platforms
contains android-28
folder only.
The reason why android-28 (corresponding to Android v9.0) is selected is because there are restrictions depending on the Java version installed and the Qt version installed.
If $HOME/Android/Sdk/platforms
does not contain android-28
folder only, follow the instructions at the next step to set things up correctly.
cd $HOME/android-studio/bin && ./studio.sh
(skip / cancel if no SDK found)more actions
and then SDK manager
SDK Platforms
tab, the following is installed (Show package details and unhide obsolete packages): (Android 9.0) Android SDK Platform 28 and Sources for Android 28.SDK Platforms
tab.SDK Tools
tab, the following is installed (Show package details and unhide obsolete packages): (Android SDK Build-Tools 34) v28.0.3, Android Emulator any version, Android SDK Tools (Obsolete) v26.1.1.cd $HOME/Downloads \
&& wget https://dl.google.com/android/repository/platform-tools_r28.0.3-linux.zip \
&& sudo apt-get install unzip \
&& unzip platform-tools_r28.0.3-linux.zip \
&& rm -r $HOME/Android/Sdk/platform-tools \
&& mv platform-tools $HOME/Android/Sdk
cd $HOME/android-studio/bin && ./studio.sh
(skip / cancel if no SDK found)more actions
and then SDK manager
SDK Tools
tab, the following is installed: NDK Side-By-Side v21.4.7075529 (equivalent to r21e). According to the Qt Website, this is the one recommended for Qt5.15.2.:hand: Make sure that $HOME/Android/Sdk/ndk/21.4.7075529/platforms
contains the folder android-28
.
:bulb: The NDK corresponds to the minimum version required to run the app. Technically, you could choose a lower version than Android API 9.0 (android-28).
Download the Qt version which matches the one in $PYQT_CROM_DIR/examples/demo/demo_project/sysroot.toml
from the open source online installer:
sudo apt-get install libxcb-xfixes0-dev libxcb-xinerama0 \
&& cd $HOME/Downloads \
&& wget https://d13lb3tujbc8s0.cloudfront.net/onlineinstallers/qt-unified-linux-x64-4.6.1-online.run \
&& chmod +x qt*.run \
&& ./qt-unified-linux-x64-4.6.1-online.run
A Qt window will appear on which you can sign up:
cd $HOME/Downloads && ./qt-unified-linux-x64-4.6.1-online.run
Qt5.15.2
(and other packages you might want)$HOME/Qt5.15.2
:hand: Make sure that you can access $HOME/Qt5.15.2/5.15.2
and that the folder android
is located inside of it.
:bulb: The package libxcb-xinerama0
is installed to prevent an issue inherent to Qt5.15 (but solved in Qt6) with xcb
Qt platform plugin, according to QT DEBUG reports.
Load the environment variables on terminal startup with:
printf "%s\n" \
"" \
"# Load extra environment variables for PyQt-CroM" \
"source $PYQT_CROM_DIR/utils/resources/path_setup.sh" \
"" \
>> $HOME/.bashrc \
&& source $HOME/.bashrc
Start the building process of the .apk with:
cd $PYQT_CROM_DIR/utils \
&& python3 build_app.py --pdt $PYQT_CROM_DIR/examples/demo/demo_project/config.pdt --jobs 1 --target android-64 --qmake $QT_DIR/android/bin/qmake --verbose
:hourglass_flowing_sand: Let the app build (it may take a while). The app is built when you see "BUILD SUCCESSFUL".
:bulb: _The Android Manifest, build.gradle
and gradle.properties
can be checked at debug stage in $PYQT_CROM_DIR/examples/demo/demo_project/build-android-64/android-build
._
The generated DemoCrossPlatformApp.apk
can be found in $PYQT_CROM_DIR/examples/demo/demo_project/releases/<build_date>
.
You can then either:
my games
and install the .apk, run the app offline:trophy: Congratulations! You have completed the tutorial. You can view the demo app running on an Android phone.
:arrow_heading_up: Back to TOP
:mag: This section describes the steps to generate an Android
app (.apk) from a custom PyQt5
app.
:bulb: Make sure to go through the Getting Started tutorial to correctly setup your machine and environment.
:warning: _In this section, placeholders are defined between <>
. For instance, <pkg_name>
can be demo_pkg
or test_pkg
._
Start by creating a project folder:
<project_name>
wherever you want (and remember the absolute path of its parent folder referred to as <absolute_path>
)Inside of the project folder, create a python package to hold your PyQt5
app:
<project_name>/<pkg_name>
<project_name>/<pkg_name>
with at least __init__.py
file and a <main_file_name>.py
script (you can add more files if required by your package)_Note that the <main_file_name>.py
must contain a unique main()
function (or any similar distinctive entry point)._
:bulb: _An example of python package is given in the demo project folder._
Inside of your <project_name>
folder, add the sysroot config to specify application dependencies:
sysroot.toml
and populate it with all the modules used by your app._For instance, if you imported QtSql
in your PyQt5
app, then you must include QtSql
in [PyQt.android] installed_modules
._
:bulb: _An example of sysroot config is given in the demo project folder._
Inside of your <project_name>
folder, add the pdt config to specify python dependencies and build requests:
config.pdt
and configure itTo configure the config.pdt
file, you need to understand and use the various areas shown in the following pictures:
config.pdt
file with: cd <absolute_path>/<project_name> && pyqtdeploy config.pdt
.Application source tab > Name area
, add the <app_name>
with no spaces. This is the app name shown at export time.Application source tab
, click on the Scan
button to select your <project_name>/<pkg_name>
folder.Application source tab > Application Package Directory area
, tick the files and folders you want to include into your application.Application source tab > Entry point area
, add the <pkg_name>.<main_file_name>:main
to tell where the entry point of your application is.Packages tab > Sysroot specification file area
, click on the file icon to the right to select the desired sysroot.toml
file.Packages tab > Standard Library area
, tick all the python libraries you have imported in your python application. You can leave the coloured blocks as they import required libraries to build the python application.Packages tab > Core Packages area
, tick all the external packages that you have imported in your python application. You can leave the coloured blocks as they import required libraries to build the python application.config.pdt
with Ctrl + S
and close it.:bulb: _An example of pdt config is given in the demo project folder._
:bulb: For more information about pdt files, read the Riverbank website page.
Generate the <app_name>.apk
file using:
cd $PYQT_CROM_DIR/utils \
&& python3 build_app.py --pdt <absolute_path>/<project_name>/config.pdt --jobs 1 --target android-64 --qmake $QT_DIR/android/bin/qmake --verbose
:bulb: _The <app_name>.apk
can be found in the <absolute_path>/<project_name>/releases/<build_date>
folder._
The most nerve-wracking part of deploying an application is the debugging part.
Therefore, make sure that you have added a logger to your application and that you use an Emulator or a physical device to confirm your expectations.
To setup an Emulator, refer to Android Emulator setup.
:arrow_heading_up: Back to TOP
:mag: This section offers feature examples to enhance your custom PyQt app.
To discover or analyse PyQt5 features, look at the section dedicated to PyQt5 features.
:arrow_heading_up: Back to TOP
:mag: This section provides a detailed tutorial on how to release your custom app onto main app stores.
To learn more about releasing your own app on app stores, follow the online tutorial.
:arrow_heading_up: Back to TOP
:mag: This section offers advice to get unstuck when creating your app.
To find out about common setup and running issues, look at the section dedicated to Common issues.
:arrow_heading_up: Back to TOP
:mag: This section describes the broad roadmap to deliver a functional repo.
:arrow_heading_up: Back to TOP
Repository created and maintained by Achille Martin.
:clap: Gigantic thanks to Phil Thompson, the creator and maintainer of PyQt and pyqtdeploy.
:heartpulse: Sincere thanks to the well-intentioned international developers who create apps benefitting the community.
_For more information about licencing details, take a look at the section dedicated to Licencing._
:arrow_heading_up: Back to TOP
:star2: Do you feel that you can make progress with your own projects by converting your PyQt5 apps into cross-platform apps?
Please support PyQt-CroM by starring, advertising and sponsoring it.
:open_hands: Do you feel stuck with your projects?
Get customised help from me on Fiverr.