Building cross-platform Graphical User Interfaces is hard. There are a few options these days, all of which have their pros and cons. Over the years I’ve used Electron Python + Qt, Python + Tkinter, Python + Browser, & Flutter for building GUI applications for various projects.
Electron
Electron is by far the most popular of these options. The core idea behind Electron is to allow the frontend to be written in JavaScript as it would be for a browser, while at the same time bundling in a NodeJS-backed end. One of the downsides of using Electron is that the compiled executable is huge. The whole of Chromium gets included in the bundle. The smallest electron application is around about 100–150MB these days.
Python + Qt
Qt is a GUI framework that has been around for a very long time. It is a C/C++ project which has bindings to many different languages, including Python. A full GUI application can easily be built in Python using all the power of Qt. Qt is fully featured and works really well. The downside is that because of licencing, all the Qt libraries get included when compiling an application using pyinstaller. These are huge. Again, it is hard to build a project under 100MB.
Python + Tkinter
Tkinter is a really old GUI framework that is built into Python. While it does the job, the GUI components are pretty basic and it lacks a lot of features that are expected these days. From my experience, it is hard to get a Python Tkinter project to behave consistently across platforms. Components render quite differently which means a lot of platform-specific code needs to be written. The upside is that compiled GUI applications can be only a few MB in size.
Python + Browser
The approach I’ve found myself using most frequently is to build a client-server system in Python with a JavaScript frontend. The server part is written in Python. This serves the frontend as if it were a web app and also provides an API server to access the backend functionality. WebSockets can be used to communicate between the front-end and back-end for a responsive system. Python can even launch a browser when the application boots. This works quite well. Compiled executable sizes are small, and the full capabilities of the browser mean modern interfaces can be written. The downside is that the “desktop” application is actually running in the browser.
Flutter
Flutter is the new kid on the block. It is a framework based on the Go language. It is quite easy to work with and build interfaces. Compiled executables are small, the interface looks good and modern, and the GUI is very fast. The downside (for a web developer) is that a new language needs to be learned. The other downside is that there are not as many mature libraries for Flutter as in the Web world, which can pose a problem if complex functionality like animated graphs is needed.
My new favourite — pywebview
The latest framework to try is pywebview. Building desktop GUIs in pywebview is kind of similar to Electron. The back end is written in Python, while the frontend is written in any modern JavaScript framework. The magic sauce for pywebview is that you can call JavaScript methods from Python and Python methods from JavaScript, all without needing to use a server-client system such as WebSockets. The other really nice thing about pywebview is that it loads up in its own window, so it looks like a real desktop application. It does this by leveraging the OS browser (chrome, edge, safari) or for Linux it falls back to Qt-webviews, which makes the compiled executables really small (except for Linux).
So far, I really like pywebview. Development is fast because I can leverage both the mature JavaScript ecosystem as well as the mature Python ecosystem. By using a watcher, I can auto-restart the Python server when code changes are made, and by using a modern JavaScript framework I can leverage the live reloading that provides. I can get great-looking user interfaces with great backed support.
If you are looking to build a modern GUI, take a look at pywebview.
Check out my follow-up article on using Pywebview with the Quasar Framework for the ultimate development experience.