Python GUIs
pythonguis.com
pythonguis.com
A few days ago I tried getting a simple PyQtWebengine example working using pyqt6 and failed miserably. It was a frustrating experience for sure
I have some (ancient) experience in RAD. Once per year I try picking up React/Vue/Angular or whatever is the current fashion, but I get stuck. It's just so _insane_.
Back in the dialup days, my modem was plugged into a homebrew Linux firewall/router so that I could use the Internet from multiple machines at once. Which outside of a large business or college campus, was considered pretty much advanced wizardry back then. The problem was that I had one phone line and couldn't tie it up all the time. I wanted to be able to open a program on the desktop of another computer, click a button marked "connect to internet" and have that talk to the server to start the dialup process. And then also a "disconnect" button to hang up later. With a little text box to show any errors and whatnot. There were some half-solutions to this in existence at the time, but nothing that fit my exact use case.
I had been beating my head against various Perl experiments which weren't getting me anywhere until finally someone on IRC said, "oh, have you tried Tcl/Tk?"
Tcl was so easy to learn that I had a working proof of concept by the end of the day. Another couple of days to tidy it up. Used it daily for a few years until DSL came to my area.
These days, if tcl/tk doesn't suffice for my project, then I just move onto another environment entirely.
I'm looking to dabble again. Is there anything similar to RAD these days? It really did make building simple GUIs very easy.
Visual basic was different because there was only one way to create a button, so no way to over engineer a new button component. All apps looked the same and nobody cared.
I never cared much for VB as a language - but the IDE around it and the ability to very quickly create complex GUI applications was phenomenal.
Of course Electron is overkill for a single-button application. But Visual Basic is absolutely going to be a headache if you want a custom GUI.
Pick the tool that's right for the job!
I build this with Electron: https://videohubapp.com/ Good luck having infinite scroll in a gallery that is butter-smooth using something else (that also doesn't require months of learning new tools) and is cross-platform(!!!).
We actually cared a lot, just in the opposite direction - apps which didn't look the same were weird and bad.
This has got to be one of the funniest opening lines, especially in response to visual basic.
I would begrudgingly accept electron if it had the same "open program, click button , draw a button, double click button, write code" experience that VB had
Former VB devs pine for the usability and speed they once enjoyed. But most tech ecosystems that are self-contained enough to benefit from focused/lightweight devtools can't support a player large enough to develop them. And the ecosystems that are big enough are managed by megacorps that are more interested in brokering consumer data than streamlining the developer experience. I too would love to see a renaissance of RAD but I can't figure out who would pay for it.
It is a niche (let’s be honest, desktop development is also one), but it has a surprising amount of libraries available as well.
GoVCL's author built a C library called liblcl [2] which is what GoVCL uses to control the GUI, so if you know C you can use it instead of Go.
I'm building a lightweight Steam chat client with GoVCL so that I don't need the official client that takes like 200-300mb ram just to show text [3].
[0]: https://github.com/ying32/govcl
[1]: https://www.lazarus-ide.org/
[2]: https://github.com/ying32/liblcl/blob/master/README.en-US.md
wxWidgets is mostly licensed under an LGPL analog with linking exceptions intended to permit distributing binaries under any license you choose. No part of wxWidgets, including wxPython, has a license more restrictive than the LGPL.
Isn't that because different platforms are different? This should be a feature. "Cross-platform that feels native", because each platform has a different definition of "native".
IME wxWidgets was always better than Qt or any other of the high-level piles of bloat. For example, its layout system would actually use the platform-native, rendered sizes of components, instead of the native components only being a skin over a secret other layer that has its own input handling (looking at you, Qt/GTK).
To some extent they are; I don't mind having Windows-native-looking widgets on Windows and Linux-native-looking widgets on Linux.
But programmatically, code that is designed to do a particular function should do it the same on all platforms. That's the point of having a cross-platform toolkit. If I end up having to write a lot of platform-specific code to handle quirks, I might as well just ship separate apps for each platform. It's been a while so I don't have specific examples, but that's generally what I remember running into.
Of course a lot of this will depend on what specific things you are trying to do. One item that I do remember having particular issues with was multiplexing network I/O with the GUI--which is inherently difficult because both of those things want to run their own event loop. Qt has a built-in "widget", QSocketNotifier, to bring network I/O events into its GUI event loop, but wx does not, so I had to roll my own, and it took different tricks on different platforms to make it work (and it was still clunky even then). But many GUI applications don't have to do that.
that's weird, wxWidgets' job is supposed to be to handle this for you.
> One item that I do remember having particular issues with was multiplexing network I/O with the GUI--which is inherently difficult because both of those things want to run their own event loop.
The UI always has to run on the main thread, so why not run the non-UI tasks in a separate thread and send events between the two to communicate? https://wiki.wxwidgets.org/Inter-Thread_and_Inter-Process_co...
Or was wxWidgets 3 not out when you were playing with it last?
I don't think so, I think 2 was the latest version I worked with.
> why not run the non-UI tasks in a separate thread and send events between the two to communicate?
Sure, you can do that, if you're willing to deal with all the extra complications involved with having multiple threads and coordinating between them. For some applications that's necessary, but in many cases none of the events, either GUI or network I/O, require CPU intensive responses, so you don't need separate threads for performance, and having them all in one event loop makes the code a lot simpler.
This is weird. Having the worker thread separate from the UI thread is a good separation of concerns regardless of whether you need the thread for performance or not. I don't remember if wxWidgets 2 even had message passing between threads, though.
I'd invite you to try wxWidgets 3, it seems to have changed a lot (for the better).
It can be, but it has a cost in code complexity. Sometimes that cost isn't worth paying.
> I'd invite you to try wxWidgets 3
Yes, it sounds like it's worth me taking a look. I have a Python GUI package [1] that right now only supports Qt 5 in its latest version; it would be nice to put wx support back in.
Update from my previous post: I took a look at release dates and wxWidgets 3 was available as far back as 2013, so that is the version my comments were based on (wxPython's version 4 series is the latest that's based on wxWidgets 3, that version of wxPython is the latest I've tested with).
this is the most modern GUI (in a console or not) framework you'll find for Python right now.
- CSS, why?! It does not really work like CSS when it comes to positioning things, overlapping and so on. Compared to previous versions where these properties were in a dict or sent in to the component, they are now in either big string blocks or in separate files, removing syntax highlighting and/or locality.
- Cannot easily use debugging such as PDB because it hijacks Traceback and uses async. Maybe fine if you rely on other debugging tools.
- It lacks simple off-the-shelf components such as menu bars, so I built my own, but run into annoying artifacts as mentioned before.
Rich, the underlying rendering library is good, and simple enough. I ditched Textual for prompt_toolkit, and can still use Rich to render things in pt.
I threw all of that time away, and had it all working in Lazarus/Free Pascal in less than 2 weeks.
Most web based programmers have no clue how badly "modern" tools are compared to the VB6/Delphi era. Everything is worse, except for GIT... GIT is brilliant.
---
Also, my personal wiki of choice is WikidPad, which is distributed as an executable for windows, and works just fine. I can't move to Linux, because it's distributed as source there, and WxWindows made a breaking change to one of their key parameters to dialog function calls, so none of the dialogs work properly, though it does show text. It's effectively read-only and broken as a result.
Personally, if I'm writing software that needs to talk to a human I'll just build a web interface instead of a GUI.
It allows me to quickly slap a GUI on an existing script that accepts command-line-arguments. In the end, I get the best of both world: Discoverability from the GUI, automation through the script, and automatic feature parity between the two.
Downside: Control over the GUI layout is basic, and only "standard" GUI features work, but I never felt limited when using it.
I ended up making a flask app and launching a browser. It seemed to be 100x easier.
I would prefer to make native GUI apps but it's just so much more difficult.
All the options fall short somehow, but guess what, its not much better in any other language. The GUI problem is not truly solved.
Unless picking a solution from the start and testing it throughout, I find that the most challenging.
But it's still considered challenging when you compare with any other compiled language, where you can get an executable out of the box. I ship Python desktop apps at work and it's remarkable how much code we accumulated over the years just to deal with the "interpreter in bundled/exe mode".
As a showcase I've built two simple utils with python and tk (and pyinstaller):
- https://github.com/spapas/pdfmerger a simple tool to merge pdfs into one
- https://github.com/spapas/pomo ; a simple pomodoro timer
Using the after or after_idle methods [2] to post a callback to the main thread also works, and seems easier to me since it allows you to pass arguments.
In this particular example, where the background thread is just used as a timer, you could remove the threading entirely if you use after to let Tkinter handle the timer.
But as always, I turn to PEP 20, in particular "There should be one-- and preferably only one --obvious way to do it." Batteries ought to be included. I'm hardly a language designer, but more and more I care less about things like syntax and such, and more about having as much as possible already built out, so I can focus on the particulars of a problem, rather than having to endure a "evaluate a bunch of alternatives" phase for each little thing.
It's a tall order, and a growing one, but I think whatever the next big language is, it will have that kind of focus.
I don't just want something bundled with Python, I want that thing to be the undeniably best choice. I want "batteries included" to mean that I wouldn't bother to look for anything but what came with the language.
Many libraries, and framework-type things seem to have come and gone, while none have really 'taken hold', so to say. Is this the case? And, specifically, what is the big hurdle to a widely accepted GUI library in Python?
https://python-prompt-toolkit.readthedocs.io/en/master/
I'm working on an interface for an LLM (large language model), and prompt_toolkit seems to be the only library with enough text-buffer features for me to implement everything I want.
It's quite imperative-feeling though. Have to keep references to individual widgets if you want to do anything with them later.
For me the docs were barely enough to get started, and completely left out some of the features I'm using (such as the `get_line_prefix` callback); it took me a lot of messing around to figure out how to do what I wanted.
But it was probably worth it, I'd say.
Ideally, I can build that with Python. I was thinking of DRF and React (since things like Retool are out of the question) but I'm open to any framework/stack. What is the most simple way to accomplish and maintain this?
You may want to have a look at https://streamlit.io/gallery
It is built on top of PyQt5. But be very careful if you use conda, because conda decided to rename the PyQt5 packages, resulting in near-irrecoverable env crashes if conda and pip are mixed. In that case, make sure to use conda-forge to install.
“Write your apps in Python and release them on iOS, Android, Windows, MacOS, Linux, Web, and tvOS using rich, native user interfaces. Multiple apps, one codebase, with a fully native user experience on every platform.”
Source: <https://beeware.org>
* Between starting and finishing this comment, someone brought up a third. Now we're up to seven!
It seems the author push for PyQt a bit, even though PySide has the same basic capabilities with the benefit of LGPL license (PyQt is GPL or Commercial).
- NiceGUI https://nicegui.io/#features - my favorite of the bunch, essentially wraps Quasar Vue components with accessible python. Tons of features including SPA, FastAPI under the hood, TailwindCSS. Have used it on a few projects and started contributing recently.
- Streamlit https://streamlit.io/ - if your goal is to get some python code set up with a GUI and deployed ASAP this is the best option. I have gone from 0 to a full working app in like an hour for some projects. Lots of love for it. A bit limited in terms of full-scale applications and large backend databases but it actually holds up really well.
There are a lot of other ones that people regularly recommend.
- Gradio https://gradio.app/ - really popular with huggingface and ml folks. Similar to streamlit in that it sacrifices some level of depth for speed of standing up projects.
- Textual https://www.textualize.io/projects/#textual - Building text-based UIs for the console. Seems to be pretty popular on reddit... Not to be a hater, but I have never seen a good argument for why it's worth dumping a bunch of time into this versus a web-oriented framework. They say "it's useful for products that don't need the internet", "you can use it through ssh", etc... doesn't really fit with my needs, I'll just leave it at that.
- Anvil https://anvil.works/ - a "low code" option for building python GUIs. I am pretty impressed, it has integrated databasing and a lot of plugins. If you are aiming for a scalable application for a large number of users this is probably a good options. My personal gripe with it is the number of mouse clicks it takes to do stuff but that could also be my lack of experience with the tool.
- Plotly dash https://dash.plotly.com/ - not usually thought of as a full GUI library necessarily but they have options for deploying the dashboards to the web - and the overall look and feel is nice. A good option if you have a small notebook with plots that needs wider accessibility.
My use cases are typically 10 - 50 users in an enterprise setting, so accessibility/low barrier to entry (pretty much meaning web-based) are concerns of mine. I also lean toward wanting to avoid learning overly-opinionated libraries (I put Qt and tkinter into this category). Why spend 50 hours learning Qt's way of building an app when I could use something like NiceGUI which lets you build a nicer looking app and gets you familiar with web dev concepts in the process. Imo a better use of my time.
If you want to sell something and keep it all to yourself, then go buy something. Qt will happily sell you a quite nice resellable component. If you want to reshare that which you got for free yourself, great, no problem there either.
Say what exactly is the problem that isn't either of those two situations out loud.
Use zeroRPC - https://www.zerorpc.io/