Skip to content

Foray into PyQt

I love Python. Of all the languages I’ve played with, it was the quickest I was able to do something useful in. Not just a working example, but code that served a purpose and filled a need. A large part of that is because of Python’s focus on simplicity and readability. However, most of the Python I’ve written has been fairly simplistic data analysis stuff. Import Data from a CSV or database. Sort it, processes it, turn it into useful and easy to read data, and then dump it out into a file. I’ve been itching for a bit more of a challenge, so I’ve set out to tackle something more complex.

I have also been wanting to work with GUI’s. The only times I’ve worked with a GUI was with a language purpose built for working in a visual medium. Brightscript for the Roku media player, for instance; or Lua for game mods. By design those are very limited in what they can do, limited to work within their specific framework for very specific tasks. The combination of a language as powerful and easy as Python, with the ability to write a GUI interface would open up a lot of possibilities for useful programs.

And so I started looking at UI library options. Tkinter was the obvious choice; as it is the standard Python GUI. However, I wanted something with a bit more punch than to be expected from a standard library. I entertained the thought of using Kivy, a python based gaming engine; but it was a bit far out of scope. I found the Qt framework interesting, and decided to pursue one of it’s implementations. Qt is a GUI framework that is designed to work uniformly across multiple platforms and devices. A QT GUI written for windows should be easily transferable to Mac, Android, or any other device. QT also has bindings in numerous other languages, including C++, Java and Perl. Knowledge of QT would help me beyond Python, plus it is very flexible and powerful. I’m always a sucker for learning multiple things at once, so I started looking at the QT bindings for Python

PyQt5

PytQt5 is the most recent version of the most popular QT binding for Python. It has either a GPL (all software using it must also be open source) or a $500 commercial license which allows distribution of a product without making it open source. PySide, the strongest alternative, has a LGPL which allows distribution of your product without it being open source as well. PySide is a major version of Qt behind and seems to get less love in the Python community. My choice of PyQt5 vs PyQt4 or PySide was largely driven by the fact that I’m not concerned with licensing as I do not anticipate selling any of my projects and a healthy dose of wanting to work with the latest tools. I figured that once I had a solid knowledge of Qt5, if I had to step backwards to Qt4 it would be a small and easy step.

Diving into PyQt5, however, was a surprisingly big step. A solid understanding of python’s class system and threading are required. This is further complicated by PyQt using it’s own threading system separate from Python’s threads, and the use of Qt specific “Signals and Slots” system to communicate between objects and threads. My first sign of things to come was my inability to find the main program loop in the first tutorial. I know it sounds stupid, but check out this example. It will open a window and hold it open until the user manually closes it. But it has no apparent loop to wait on user input or to act upon that input.

The answer, btw, is that app.exec_() hands everything over to a Qt main program thread; it appears that everything you do before that is setting the program up, and then QApplication.exec_() handles running it. I think. I wasn’t able to find much documentation or discussion about it, and I struggled to find the proper way to set things up for hand off.

Signals & Slots

The Signals & Slots are the construct Qt uses to communicate between objects. If you press a button in a Qt GUI, it’s sending a signal object to any slot the originating object has been connected too. This is origin centric; you connect signals to slots, but you do not connect slots to their signals. In this way the design of the input (and thus the UI) drives development of the application. It’s my understanding that is a common model for UI toolkits to follow, but the Signals & Slots construct appears to be unique to Qt.

Unfortunately, I wasn’t able to really grok this. I had no problem using pre-existing actions and Signals, and passing those to various slots. But whenever I started trying to generate my own signals, things started to fall apart. I struggled with object inheritance until I was able to connect Signals to slots, but even then the Signals I sent never seemed to work out right.

Moving on

Ultimately, between the issues with setting up threads to hand off to QApplication.exec_() and my inability to understand Signals and Slots well enough to generate my own, I was unable to make any headway on actually generating a useful program. I always felt that I was one (or two) Eureka moments away from having it all fit together, but it never came. Don’t get me wrong; I had no problems getting a program with a pretty UI to run. And those UI elements even connected to each other. But there was plenty of Magic in there… code that I didn’t understand but needed in order to get things to work. And I wasn’t able to get the UI to do anything interesting… for instance, I was never able to get it to display a simple count down.

When I’m learning something, especially if it is just for personal projects, I have a rule of always producing something. Usually this just means focusing on simplifying a problem until I get the basics to work, and then expanding from there. The idea is to avoid getting bogged down under too many levels of complexity that I can’t make any progress. By ensuring that I’m able to produce working and usable code, I ensure that I’m actually solving problems, learning new things, staying interested, and have something to show for my efforts. Unfortunately for PyQt, I’m having to take the step of dropping it. I hope to return to PyQt some day and hope that approaching it with fresh eyes and more understanding will give me those eureka moments I’ve been looking for. Until then, I’ve taken up Tkinter.

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*