
Guietta – Python module to create simple GUIs - todsacerdoti
https://github.com/alfiopuglisi/guietta
======
raghavtoshniwal
This is so timely! I am teaching CS to some high-schoolers and they just got
introduced to Python, I want to hook them by getting them to make something
that they can play around with. Could use this there :D

Somehow, it feels like, CS education is getting both easier as new low
friction tools are being made available each day and getting harder because
the sheer complexity and number of things to know to really understand
anything at all the levels of abstractions is getting more complicated.

~~~
gljiva
As a former high-school student who has done many little projects with tkinter
at that time, I would recommend against dumping tkinter altogether for several
reasons:

\- with higher complexity comes higher versatility. I liked how it enabled me
to be creative \- there are two well-written reference websites for learning
it easily despite complexity (and that's important if you want your students
to like/learn to read the docs) \- the tkinter being shipped with Python meant
quite a lot to me

However, the reason I did that many projects is that part of my class wasn't
really into programming, so if you think that learning and using this will be
significantly easier than tkinter basics, go with it, but I would recommend
leaving tkinter at least as an option for "those who want to know more", i.e.
students who are considering studying CS.

~~~
GeorgeTirebiter
What are the URLs for those two well-written references you mention? Thank
you.

------
mindv0rtex
For not too elaborate GUIs in Python, I think TraitsUI is a really neat
library:
[https://github.com/enthought/traitsui](https://github.com/enthought/traitsui)

------
galacticdessert
Based on the very limited documentation it seems to follow a similar approach
to PySinpleGUI
[https://github.com/PySimpleGUI/PySimpleGUI](https://github.com/PySimpleGUI/PySimpleGUI)

PySimpleGUI is indeed simple and quick, not very elegant but useful for small
utilities.

~~~
alfiopuglisi
Yes, I was inspired by PySimpleGUI (and say as much in the introduction:
[https://guietta.readthedocs.io/en/latest/intro.html](https://guietta.readthedocs.io/en/latest/intro.html)
). But I felt that PySimpleGUI did not go far enough in making things simple.
It also supports multiple backends, so that may be a reason to keep things
more structured. Guietta is just a thin wrapper over QT.

~~~
app4soft
> _Guietta is just a thin wrapper over QT._

So, any pro'n'cons in comparison to PyQt?

~~~
dr_zoidberg
Not the author, but I assume the one big pro is being a lot simpler, and the
one big con is that it limits the flexibility of the full QT bindings.

All in all, it's a wrapper that hides complexity and flexibility from you.
Might be what you need some times.

------
user5994461
>>> from guietta import _, Gui, Quit

I am not looking forward to taking over projects using that framework abusing
underscore and double underscore magic variables.

The underscore "_" is a pseudo reserved variable in python. It is used in
assignments like year,month,_ = readdate() to discard the return value and
disable the lint warning about it.

~~~
codethief
Couldn't you simply do something like

>>> from guietta import _ as underscore

to fix this?

~~~
user5994461
After spending inordinate amounts of time debugging obscure side effect caused
by "import as" and "from import". I'd reject that "from import as" on sight in
code review.

~~~
detaro
Any hints towards what kind of issues those cause? I could see some around
relative imports, or something else?

~~~
user5994461
Let's say you write a module httpclient doing this:

    
    
        from ssl import sslsocket
        import httplib as hlib
    

You can think of the code above as remapping and/or duplicating the whole
library it's importing. Python imports involve complex local and global states
(I don't pretend to understand most of it).

One direct effect on usage is that users of the library can call
"httpclient.sslsocket" and "httpclient.hlib" as if they were provided by the
library (the author certainly didn't mean to). This creates problem down the
line when the author try to change the internal dependency, and this extends
to other code also doing "import httpclient.sslsocket as sslsocket", creating
problematic hidden dependencies.

More generally, this affects all import dependent features, like
reload(module), mock, sys content, etc... imports are looked up and tracked by
full path which doesn't always work as expected when paths are hot patched as
above.

I used to work in a python shop (millions of line in total across the
organization). Regularly had the problem with interns and new graduates
abusing imports as above (sometimes even trying to change the existing imports
because they though this was the better syntax). Then they couldn't pass their
own tests (every new module must have a test) and asked for help after few
hours of trying. Changing to a normal "import xxx" solved the problem. It's
not always clear what was the exact issue, except side effects due to imports.

~~~
codethief
Let me take the opposite standpoint here and play the devil's advocate.

> users of the library can call "httpclient.sslsocket" and "httpclient.hlib"
> as if they were provided by the library

Well, they obviously shouldn't. And maybe they also shouldn't write Python
code to begin with because, clearly, they're not able to adhere to Python
conventions. Besides, why do you as the library developer care so much about
what the users of the library do? If they don't follow your API specifications
(proper API documentation should tell the users what they should and shouldn't
do), it's their fault. I mean, people can and will shoot themselves in the
foot all the time and in various ways. There's is nothing you can do about it.

> which doesn't always work as expected when paths are hot patched as above.

There is a reason why hot patching (and, by implication, mocking) needs to be
done with care and only if you fully understand the consequences.

Regarding issues with mocking specifically, I suppose you're referring to
nasty questions like [https://stackoverflow.com/questions/14341689/how-to-
mock-usi...](https://stackoverflow.com/questions/14341689/how-to-mock-using-
patch-relative-paths/) ? Again, these things need to be done with care. (And
of course the code also needs to be written in a testable way – no surprise
here – and mocking should be done only if you've exhausted all other options.)

> It's not always clear what was the exact issue, except side effects due to
> imports.

Like you I am a Pythonista but I have honestly never run into any problems
with selective imports (`from X import Y`) or import renaming (`import X as
Y`) and much less even know what problems you're talking about. Overall, I
find Python's way of importing modules rather straight-forward. (That is, as
long as PYTHONPATH and __name__ are set correctly. From my POV, this is the
only seriously annoying caveat.)

Anyway, I'm very open to changing my opinion but I'm afraid you'll have to be
more specific about the issues you're encountering so often. (If you really
did encounter them so often, I would think you would have noticed a pattern by
now? No offense.)

------
Okkef
Every time I see something like this I think back to the glorious days of
Borland Delphi with it's beautiful drag&drop GUI builder.

~~~
alfiopuglisi
Actually I started to develop Guietta exactly because using the QT GUI builder
(Qt designer) was often too time consuming for simple applications.

Designer works great for GUIs with complex layouts. Having an intermediate XML
representation puts a lot of distance between your code and your GUI.
Sometimes this is good, other times is not. I rant a bit about this at the
start of the introduction:
[https://guietta.readthedocs.io/en/latest/intro.html](https://guietta.readthedocs.io/en/latest/intro.html)

~~~
murgindrag
Delphi wasn't like that.

There'a a gap a mile wide between

1) tools like Delphi, VisualBasic (the classic version, not .net), and to some
extent, HyperCard

2) GUI builders, which were popularized by Visual C++

#1 doesn't have (visible) layers or abstractions. It's a different way to
represent your program. You place a few controls, tie them to actions (code),
and that's your system.

#2 is like onions, with lots of messy layers, and tend to be way more
cumbersome to deal with than the code itself.

I don't know of modern-day graphical programming systems. I haven't kept up
with Delphi, but people who have claim the last useful version is Version 7
from 2002. After that, it went through some messy transition.

~~~
user5994461
There is one GUI builder in Java I forgot the name, a plugin for Eclipse from
Google, that allows to build GUI by drag and drop and jump into the code. It
works directly by reading and writing any java code file, there are no extra
files and layers of abstraction. It could understand Swing, SWT and a couple
other major UI frameworks.

That's the only thing I know that's really seamless like old times.

~~~
yCombLinks
WindowBuilder

------
maddyboo
If you want to present GUIs from shell scripts, I highly recommend zenity
and/or yad:

[https://gitlab.gnome.org/GNOME/zenity](https://gitlab.gnome.org/GNOME/zenity)

[https://github.com/v1cont/yad](https://github.com/v1cont/yad)

~~~
Abishek_Muthian
Would have loved few examples of GUI on the project repo like in the OP repo
(or) I didn't see where I should have been looking.

~~~
maddyboo
I agree, there should be some screenshots in the READMEs. Here are some
example uses of yad with screenshots:

[https://sanana.kiev.ua/index.php/yad](https://sanana.kiev.ua/index.php/yad)

------
zubairq
As the author of another open source GUI builder tool
([https://github.com/zubairq/pilot](https://github.com/zubairq/pilot)) I think
that the simplicity of tools like Guietta really make it easy to play around
and build things fast, so I like it

------
rembicilious
Great idea! Tkinter always looks a little dated and PyQT is more than my brain
wants to deal with when I need a simple GUI.

~~~
toyg
_> Tkinter always looks a little dated _

"A little"... it's straight outta the '90s. I am as nostalgic as anyone but
even I don't particularly long for that æsthetic.

~~~
anthk
A true nostalgic won't give a shit on tk aesthetics but functionality.
Changing the font is one line away.

~~~
preommr
Did... did you just gatekeep feeling nostalgic?

------
samanator
I love how the imports in
[https://github.com/alfiopuglisi/guietta/blob/master/guietta/...](https://github.com/alfiopuglisi/guietta/blob/master/guietta/guietta.py)
are ordered from shortest to longest. Makes them look like stairs! Very
aesthetically pleasing :). Might take that up in my next project.

~~~
skocznymroczny
Some of Python linters enforce such style. If you enable pylint or black I
think they do that by default.

~~~
diarrhea
black sorts alphabetically, with standard lib first, then 3rd party imports,
and user/local imports last. Blocks are separated by a blank line. `from ..`
imports come after `import ..`.

Especially the alphabetic ordering is important in my view. Makes
parsing/reading and spotting duplicates much easier. It is also PEP8 style
[0].

For all these reasons, I think the pyramid style is awful in comparison.

0:
[https://www.python.org/dev/peps/pep-0008/#imports](https://www.python.org/dev/peps/pep-0008/#imports)

~~~
StavrosK
Black doesn't sort imports at all.

~~~
spappal
And PEP 8 doesn't mention sorting the imports. There are even counterexamples
which aren't alphabetically sorted. It does mention grouping though.

Since Python imports can have side effects, the order can matter. But to the
extent that it doesn't break anything, alphabetically sorted groups seems
deterministic and readable.

I think this might be the most popular implementation for auto-sorting:
[https://pypi.org/project/isort/](https://pypi.org/project/isort/)

~~~
StavrosK
isort is the most popular, but this is the best by far:

[https://github.com/asottile/reorder_python_imports](https://github.com/asottile/reorder_python_imports)

------
markussss
This looks great. I have previously written a small GUI application with Qt
where it's just a slider and a text label, and when the value of the slider is
changed, a command is ran and the label updated. In quickly hacked together
Python/Qt, it's 71 lines. It seems like I can cut that down quite a lot by
using this. I will have to test it. Thanks!

~~~
alfiopuglisi
If you get around to test it, I would love to hear the results :)

------
carapace
I once made a simple little GUI generator based on effbot's "Generating
Tkinter User Interfaces from XML"[1][2]. I added a tiny parser (written with
SPARK[3]) that converted a simple DSL to XML (technically an ElementTree
object, the actual XML isn't serialized/emitted at any point) which is then
"realized" as a tree of Tkinter widgets with event callbacks.

[1] [https://www.effbot.org/zone/element-
tkinter.htm](https://www.effbot.org/zone/element-tkinter.htm)

[2] [https://github.com/calroc/pygoo](https://github.com/calroc/pygoo)

[3]
[http://pages.cpsc.ucalgary.ca/~aycock/spark/](http://pages.cpsc.ucalgary.ca/~aycock/spark/)
"Scanning, Parsing, and Rewriting Kit"

------
milansuk
Nice work. I have one out of curiosity question.

In the example, there is the button called 'Calculate' and then action define
in "gui.Calculate" block. But what if the name of the button was 'Calculate
it'(with the space between words)? The action header would be gui.'Calculate
it'?

~~~
alfiopuglisi
Hello, Guietta author here. For most widgets, the name is derived from the
widget text removing all non-alphanumeric characters. So in your example it
would become gui.Calculateit

It is also possible to set a custom name using a tuple syntax (widget,
'name'). Like this: (['Calculate'], 'myname')

------
marczellm
I wrote a XML/YAML based declarative wrapper around tkinter once:
[https://github.com/marczellm/tkpf](https://github.com/marczellm/tkpf)

------
Perseids
Slightly off topic: Does somebody have a recommendation of a toolkit or
library for simple data entry and display with Python? Basically I want to
replace Excel/Calc for mostly tabular data, because I hate the programming and
data access model (e.g. instead of writing B$8 or sum(A9:A23) I would like to
have map/reduce function with reasonable variable names). But the presentation
and entry speed is much better with spreadsheet software, than when using some
ad-hoc plain text format for simple parsing with python.

~~~
hakanito
Jupyter notebook with pandas DataFrame

------
Bomberus
Does it support reactive data binding? Like:
[https://github.com/Bomberus/LayoutX](https://github.com/Bomberus/LayoutX)

~~~
alfiopuglisi
No, you have to manually update widgets assigning them their new value
(strings, and for labels also lists and dicts). I will think about such a
feature but I have no experience with such dynamic frameworks :)

~~~
Bomberus
Shouldn't be too hard. For example you could use:
[https://github.com/ReactiveX/RxPY](https://github.com/ReactiveX/RxPY).

Then your central state is assigned to a Subject and all widgets have an
reference to an observer. As soon as the central state value changes, the
callback in the observer is triggered and you can fire the update method for
the widget using the central state value.

------
toyg
_ is typically used to i18n strings with gettext, it seems like poor naming
for a layout-related function like a spacer.

Apart from that, this seems to be a wrapper on top of PySide/QT to speed up
development of basic forms. I don't find it particularly attractive, I have a
feeling one will have to drop into QT as soon as requirements get slightly
complex. Then again, if it gets more people to approach QT and desktop GUIs in
general, it's welcome.

~~~
alfiopuglisi
I realized too late that _ is used for i18n. Well, 10 minutes late maybe, but
I had already completed the first test GUI and it looked so nice that I could
not turn back :) If you have ideas for an alternative syntax, I am all ears.

~~~
mkl
How about __? That matches the magic __ in __a__.

~~~
alfiopuglisi
If you look in the tutorial, there is also a ___ (three underscores) magic
widget for special layouts :) I can see the difference between one and three,
but between two and three it becomes difficult :)

------
riffraff
This might not be obvious, but the name appears to be a pun in Italian on the
name Giulietta (Juliet), known for cars and for the shakespearean play.

It made me chuckle a bit :)

~~~
alfiopuglisi
Guietta author here. In fact I am Italian, but the name is just a diminutive
of "GUI" \- in Italian it sounds something like "small and cute GUI". I have a
friend called Giulia and she initially thought that it was dedicated to her :)

~~~
galacticdessert
I initially thought you were the enthusiastic owner of an Alfa Romeo Giulietta
:)

------
panic
I love how the buttons, since they're written as a string in an array,
actually look like ASCII art buttons. Cool stuff!

------
hobls
That's really neat. It reminds me of generating a CLI based on docstring,
which is another pattern that I like a lot.

~~~
manifoldgeo
Are you by chance talking about docopt? I love that tool!

[http://docopt.org/](http://docopt.org/)

~~~
hobls
Yep! I love it for simple projects.

------
asicsp
It says MIT license. I'm not so good with comprehending licensing terms.
PySide2 [0] is under

>GNU Library or Lesser General Public License (LGPL), Other/Proprietary
License (LGPL)

So, is it okay for Guietta to be MIT?

[0] [https://pypi.org/project/PySide2/](https://pypi.org/project/PySide2/)

~~~
phoe-krk
AFAIK a library that uses LGPL3 modules without any modification is allowed to
be licensed differently, provided that the final product allows the LGPL3
modules to be recompiled and/or swapped for others and that the source for the
LGPL3 modules is provided.

~~~
asicsp
Thanks.

I'm still confused though. If I create an application using Guietta, do I have
to follow MIT or LGPL3 terms?

~~~
phoe-krk
You can follow whatever terms you desire for your application as long as you
fulfill the requirements of the licenses of all modules that you use. In case
of MIT, it is attribution; in case of LGPL3, you need to make the source of
the LGPL3 module available and you need to make it possible for the user to
swap the compiled module you ship for their own version of that module.

~~~
alfiopuglisi
Thanks for the heads up. I confess that I did not look deeply into library
licenses while setting up the project. I will add a note about PySide2 being
LGPL in the readme.

------
blackrock
Clever. Cute for a simple little program.

But will quickly devolve into a morass if you need to do anything beyond a
simple grid.

------
yellowapple
Is including arbitrary Qt widgets doable (whether now or in the future)? A lot
of my use cases for PyQt5 revolve around QWebEngineView; would be great to be
able to throw that widget into a Guietta layout with the extra buttons and
such I'd be using around it.

~~~
alfiopuglisi
Yes, any QWidget instance can be used directly in the layout. If then you want
to reference it, the best option is to use the tuple syntax to assign it a
name: (widget, 'name'). Check the slider example out (slider.py), it does
exactly this.

------
72deluxe
Looks very simple to write, although as others have said why not use a GUI to
build the UI, eg. wxFormBuilder which has outputs to Python/PHP/C++ ?

Thought I'd mention that as it might be something useful to others.

------
als0
Cool project, some questions.

In the README, Quit is a button but doesn't appear to be consistent with the
syntax of other buttons like ['Calculate']. Is there a reason for this?

Also, how do you bind buttons to functions?

~~~
alfiopuglisi
Quit is a built-in class, because is very common. There are also Yes, No, Ok
and Cancel builtins. You could do the same writing ['Quit'] and binding it a
function that quits the program.

Binding is done using QT's signals/slots mechanism under the hood, and can be
done in several ways:

\- using the 'with' statement as in the example, but this is often limited

\- using an events layer, that is, a replica of the GUI layout, with a
callable for each widget that you want to bind.

\- using the @gui.auto decorator on a function: it will try to guess.

All this is described in the tutorial:
[https://guietta.readthedocs.io/en/latest/tutorial.html](https://guietta.readthedocs.io/en/latest/tutorial.html)
, chapter "GUI actions"

------
shepardrtc
This is just what I was looking for! I developed a very simple (and slightly
similar) TUI library, but I need to at some point move to a GUI, and this is
perfect for it. Thank you!

------
mkchoi212
This feels like markdown but for GUIs. Love the simplicity and look forward to
see what kind of interfaces people come up with!

------
cafard
Years ago, I really liked PythonCard, but the last time I looked it seemed to
have been abandoned.

------
iwangulenko
sweet! will this run on mac?

edit: tried:

"UnboundLocalError: local variable 'loader' referenced before assignment Fatal
Python error: could not initialize part 2

...

'python script.py' terminated by signal SIGABRT (Abort)"

:(

~~~
alfiopuglisi
Hello, author here. I have tested Guietta on two different macs (mine and a
coworker's) and it worked in both cases. There is no variable called 'loader'
in Guietta's source code. Are you trying the example in the github readme, or
a custom script? Which MacOS version? If you wrote your own script.py, could
you please copy it into a github issue?

------
nottorp
But is it safe to go near Qt any more?

~~~
detaro
if asked that generally: yes it is.

~~~
nottorp
Not technically, legally.

~~~
detaro
Same answer. No, it's not unsafe to touch in general.

------
IshKebab
Honestly this looks hacky and "magical". E.g. what makes 'result' different
from 'Enter numbers:'? Is PyQt really that difficult?

~~~
alfiopuglisi
'result' and 'Enter numbers:' are exactly the same thing - two QT labels. The
example code just changes the first one's text. If you run the code, you'll
see it by yourself.

PyQt is not really difficult, just boring. And a bit of magic was indeed the
intended effect :)

------
adamnemecek
I don't want to shit on anyone's work but there are so many wrappers around
qt, gtk and the others. I wish more people were writing guis frm scratch as
opposed to wrapped the same old shit.

~~~
pg-gadfly
And why is that? Would bringing water into your house by a bucket also be a
great idea? Unlikely, unless it serves another, non-obvious point.

~~~
ptx
Perhaps it would, if the plumbing takes up most of the space in your apartment
and requires complicated maintenance.

