Author Topic: GUI for Python?  (Read 3589 times)

0 Members and 1 Guest are viewing this topic.

Online Bud

  • Super Contributor
  • ***
  • Posts: 5862
  • Country: ca
Re: GUI for Python?
« Reply #75 on: June 13, 2022, 06:25:53 pm »
I’ve had about 15 million lines of it in production before. Not one issue. Even the python 2 to 3 port was smooth.
Good for you. Total opposite experience here.
Facebook-free life and Rigol-free shack.
 

Offline Karel

  • Super Contributor
  • ***
  • Posts: 1966
  • Country: 00
Re: GUI for Python?
« Reply #76 on: June 13, 2022, 07:16:11 pm »
When you report a problem on a forum related to one of the bigger python projects,
the first thing they ask you is which version exactly of python you are using.
Then they tell you to try version 3.xyz instead of version 3.xzy...
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 4438
  • Country: fi
    • My home page and email address
Re: GUI for Python?
« Reply #77 on: June 13, 2022, 09:20:13 pm »
Then they tell you to try version 3.xyz instead of version 3.xzy...
I've done that in C projects also, for the simple reason that if there has been a lot of churn in that part of the code base between the two versions, having information in which version the behavioural change occurred, tells a lot about what code might cause it.  Hell, this is exactly why git bisect exists: it is how bugs and behavioural changes in the Linux kernel are pinpointed.

In other words, it is an useful buggy code locating technique.  Please, do not think it is a way to just divert you to a new version!  I have never done that with the intention of having the end user switch to a newer version, only as a tool to pinpoint the source code involved!  I know what kind of hell version dependencies can be, firsthand.

Only when they refuse to fix the issue because it does not occur in a later version, does it actually become assholey behaviour.

Also, even if Python developers were to refuse to fix the issue (for example, for 3.8.x because the bug is not a security issue), Linux distribution maintainers often will, applying bug-fixing patches at the distribution level.  In general across many projects, sane upstream developers then relent, and release a bugfix anyway.

Why Python 3.8.x as an example?  It is listed as "security fix maintenance only", but 3.8.x is currently shipped in e.g Mint 20.3 (Long Term Support) and other Debian/Ubuntu derivatives.  I personally am currently using 3.8.10 myself, even though 3.10.y is the Stable and 3.11.z the Development version right now (2022-06-13).
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 24149
  • Country: nl
    • NCT Developments
Re: GUI for Python?
« Reply #78 on: June 13, 2022, 09:37:37 pm »
It'd have to be something actually useful, as to properly "stress" the toolkits/frameworks, and see what working with the codebase and resource files is like.  I just cannot think of a suitable example.  Even better if someone designs a suitable UI in pygubu-designer/Glade/Qt Designer, or even just e.g. Inkscape as a picture, to start with.
The latter is a good option. Draw a layout as a mock-up and code it. I've let go of the idea of using GUI design tools a long time ago. You quickly want your controls & screens to scale which is easy to do in code but very hard with controls that just sit there at a fixed position. And creating a bunch of contols using a for loop is quicker too and the spacing & position can be changed much quicker compared to using a GUI design tool and adjusting the position of every button, text, etc.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline nfmax

  • Super Contributor
  • ***
  • Posts: 1502
  • Country: gb
Re: GUI for Python?
« Reply #79 on: June 13, 2022, 09:43:54 pm »
In any case, if someone comes up with a good idea for a basic but useful GUI example program, especially if they bother to design/sketch out the UI, I do promise to try to write at least Qt (PySide2 + PyQt5) and Gtk+ (gi) implementations (on Linux, as I cannot currently test on Windows), perhaps also a tkinter/pygubu one.  (The "try" is there, because I'm still struggling with productivity/responsibility/stress management failures, and cannot promise I don't stumble on those personal pitfalls I tend to stumble on. :()

Oddly enough, I had occasion to make just such a tool a few months back. It's a 'data inspector' for signals from an ultrasound system whose purpose it is inconvenient to go into too deeply here. Suffice it to say, the development engineers were having a hard time using the application software, which does some fancy signal processing and presents measurements derived from this processing, to decide if the system was actually working as designed or not.

So I put something together in Python (since rest of the software is in Python) using PyQt5, numpy, scipy & matplotlib. It shows a tabbed interface that lets you look at a signal in the time domain or as a spectrogram, or a whole set of such signals together as an echogram (i.e. like a medical ultrasound image). With features like optional harmonic cursors in the spectrogram, time/frequency/range cursor readout in lots of different modes, and lots of control over the visualisations to bring out different features (or bugs). It's been highly revealing. Also handy to make pretty pictures to show the investors!

I started using the Qt visual designer, but in the end I kept it only for the menu structure. The rest of the interface I just wrote by hand in Python. It uses the 'springs and struts' approach which I am familiar with from ancient history. This leads to a huge __init__() method for the View object, which is inconvenient to work with. It's also a bit hairy keeping track of the slot/signal connections, since that can only really be done by the Controller. You end up having to modify two separate parts of the code for each change or addition to the UI. It's not the old VB click & code approach. But the View & Controller are both really too large & unwieldy for comfort and should be split up somehow. I didn't really try, but Qt doesn't seem to offer any help with that.

One unexpected nice feature was PyQt's threading support. It made keeping the interface live while loading data from a directory containing some hundreds of CSV files quite easy to accomplish. Complete with progress bar and cancel button!

Now we are gaining confidence in the system, the inspector is seeing less use, but it still scratches a significant itch. No thoughts of reworking it using another GUI toolkit though, and I can't disclose the code :( But perhaps it may inspire someone else
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 4438
  • Country: fi
    • My home page and email address
Re: GUI for Python?
« Reply #80 on: June 14, 2022, 06:04:11 am »
I've let go of the idea of using GUI design tools a long time ago. You quickly want your controls & screens to scale which is easy to do in code but very hard with controls that just sit there at a fixed position.
For what it is worth, I tend to use GtkGrid or QGridLayout for widget layout, much like HTML tables, which scale automatically.  I basically never use fixed layouts, as I need mine to scale according to my varying needs.

I lived through the "This web site is best viewed in 800x600 resolution" era, and hated every time I encountered that.  I didn't do it myself then, and I don't want to do it now.  I habitually browse web sites with varying (site-specific!) zoom levels, too.  (Right now, for EEVblog forums, on this particular laptop I use 120% with 14pt DejaVu Serif as default font.  For other sites, it varies between 90% and 133%.  It obviously also varies depending on the display I'm using, and the distance I am at from the display.)

creating a bunch of contols using a for loop is quicker too
True.  It really depends on the application, which is my point regarding an example.  A synthetic example won't be useful much; we really need a real-world use case for it to matter.

GtkBuilder does support <template> .ui objects in Gtk+ 3.10 and later, and in both Gtk+ and Qt .ui files you can generate objects (and object hierarchies) and instantiate them multiple times, but I prefer to create Python classes (possibly extending a suitable toolkit widget class) instead.  And I have a habit of describing things in dictionaries (in Python; in arrays of structures in C) and instantiating them in a loop.

Whatever makes the code most maintainable, but does not have any significant downsides (like slowdowns or installation quirks), is the best approach in my opinion.

Oddly enough, I had occasion to make just such a tool a few months back. It's a 'data inspector' for signals from an ultrasound system whose purpose it is inconvenient to go into too deeply here. Suffice it to say, the development engineers were having a hard time using the application software, which does some fancy signal processing and presents measurements derived from this processing, to decide if the system was actually working as designed or not.

So I put something together in Python (since rest of the software is in Python) using PyQt5, numpy, scipy & matplotlib. It shows a tabbed interface that lets you look at a signal in the time domain or as a spectrogram, or a whole set of such signals together as an echogram (i.e. like a medical ultrasound image). With features like optional harmonic cursors in the spectrogram, time/frequency/range cursor readout in lots of different modes, and lots of control over the visualisations to bring out different features (or bugs). It's been highly revealing. Also handy to make pretty pictures to show the investors!
Well, visualising signals and filters in time and frequency domains is an important tool in many sub-fields members here would be interested in.  ;)

It's also a bit hairy keeping track of the slot/signal connections
When using Qt Designer .ui files, PyQt5.QtCore.QMetaObject.connectSlotsByName auto-connects on_widgetName_signalName slots to the named signals.  Applying the Principle of Least Surprise, we can do that ourselves with just a couple of lines.

Let's assume we use a custom class, with the widget hierarchy already hanging off the ui member.  (I load this using self.ui = loadUi("filename.ui"), but it does not matter how you construct it, as long as you use widget.setObjectName("widgetName") or equivalent to give each signal-generating widget an unique name.)

Connecting all abovenamed functions in the custom class to proper signals requires just a few lines of code, after the self.ui widget hierarchy has been created (but not shown yet):
        for slot in dir(self):
            if callable(slot) and slot.startswith("on_") and slot.find("_", 3) > 3:
                widgetName, signalName = slot[3:].split("_", 1)
                signal = getattr(self.ui.findChild(QtCore.QObject, widgetName), signalName, None)
                if signal:
                    signal.connect(getattr(self, slot))

Alternatively, you can use an array of ("widgetName", "signalName", pythonCallable) tuples, and in a loop over them,
        sourceSignal = getattr(self.ui.findChild(QtCore.QObject, widgetName), signalName, None)
        if sourceSignal is not None:
            sourceSignal.connect(pythonCallable)
To include signal-to-widget-slot tuples of form ("sourceWidgetName", "sourceSignalName", "targetWidgetName", "targetSlotName"), do
        sourceSignal = getattr(self.ui.findChild(QtCore.QObject, sourceWidgetName), sourceSignalName, None)
        targetSlot = getattr(self.ui.findChild(QtCore.QObject, targetWidgetName), targetSlotName, None)
        if sourceSignal is not None and targetSlot is not None:
            sourceSignal.connect(targetSlot)
instead.

I find these "tricks" make the signal-slot stuff much more maintainable.
« Last Edit: June 14, 2022, 06:06:00 am by Nominal Animal »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf