This article includes observations, conclusions, and recommendations that are not meant to cover or represent 100% of the possible situations. In terms of GUIs, the benchmark is 80% of the use cases.
Corner cases exist in all areas of problems. There are "yea but what about...." questions you can ask about anything and everything in the universe. There's no attempt being made nor claimed that this proposal solves every GUI problem, every programmer's educational level, every runtime environment, etc.
This conversation is targeted at user code, not library code. In other words, the person writing the code and using the code is a user, not a person writing a library module.
Now there's a loaded word. It's subjective to be sure, but there are certain traits, patterns or pieces of code that make them more or less Pythonic "feeling". Another way of putting it is "I can't define it, but I know it when I see it".
Few things are truly out of reach of the beginner in Python. Look at Threads for example. After reading the two pages on Threads from the Python documentation, someone within the first month of starting their Python education can figure out how to create and start a thread. Maybe they don't know how to fully use one, but they can make and start it.
One interesting and problematic fact about the top 3 GUI pacakges in Python is that they were not written for Python. They were designed, written, and used with C++ prior to being adapted to be used with Python.
Bringing an existing GUI library into Python isn't the problem here. The problem is that they also brought a rigid definition of how a user's GUI code is be architected. All three of these packages require the user to write their GUI code using an Object Oriented architecture.
Classes are a way to create new types in Python. They are also used, heavily, in Object Oriented designs / architectures.
The "preferred" (only practical) way to use these GUI packages require the end user to design and write their GUI in an object oriented manner. Pick up a book on any of these GUI libraries and you'll see in every exercise the word Class. It's just how it is.
Sure, you can, with some effort, "get around" using classes, but it's not straightforward nor easy, a couple of the defining characteristics of being "pythonic".
Think through the Python standard library and it's many packages. Do any of these packages require you to design large sections of your code in a particular way in order to use them?
Some programming languages, like C#, utilize events and callbacks heavily. Some designs also utilize callbacks. The top three GUI packages all handle events by calling a user's callback function.
When a button is pressed in tkinter, for example, the function specified when the user created the button is called. All of the top three GUIs work this way, calling a user's function when an event happens.
Let's take queues as an example for handling "events". In the Python library there is a `queue` module that has an object called, you guesded it, a `Queue`. In some languages or libraries, a Queue object like this one would generate a callback when something arrives in the queue.
The way this `Queue` works in Python is that you `get` an item from the Queue. There are 2 modes you can use, blocking and non-blocking. Additionally, if blocking is specified, you can set a timeout value that will raise an Empty Exception when nothing is found in the queue within the timeout.
Let's get concrete so that these concepts and characteristics can be demonstrated. If you're reading this, you've likely already read about or experienced the concepts and characteristics of the three packages already discussed so no need to fill up the page with examples from the Top 3 packages.
Since everything's an object in Python and Python programmers are comfortable using objects, use objects in a way that's logical and simple, but don't require the user to create new objects of their own (i.e. they don't have to write the word class).
In order to make a button, users use the `Button` object. To show some text in the window it's a `Text` object, etc. We're just talking about using these objects, just like Theads or Queues.
#### Python's Core Types
Python's `List` and `Dictionary` types are fundamental to say the least. When first hearing about Python and its `Lists` I honestly didn't understand what the excitement was all about. I couldn't envision that a list of stuff could make a language powerful (and popular too).
OK, so how about we define our window using nothing but lists? Everyone that programs Python knows what a list is and how to operate on them too. Our window's "layout" is a "list of lists". What I mean by that is that one "row" of a GUI is a list.
What we have is a list, with two lists inside of it. Each of the interrior lists represents one row of the GUI. Looking at this layout, it's probably obvious what this window will look like.
We've got our window's interrior, now let's make a window. Like other std lib calls, such as Threads, mentioned before, it's a simple object that users interact with.
```python
window = Window('Title of window', layout)
```
Here we have defined a window, put a title on it, and we passed the layout it's supposed to have inside of it.
Our next step will be display the window and deal with what we want our button to do. Notice that unlike the 3 big GUI frameworks, our `Button` object doesn't have a callback function. How are we supposed to get these window events?
The way we're going to get the events is using the exact same technique that our Queue example earlier did. For the queue, the call is `get`. For PySimpleGUI Windows, the call is `read`. Let's add that to our program and we'll be done.
When the button is clicked, the variable `stuff` is printed. It has the value:
```
('Our Button', {})
```
It looks like what's being returned is a tuple. The first part is our button's text, called "the event" in PySimpleGUI, the second part is an empty dictionary. If there were input fields in this window, then the dictionary (another fundamental Python type) contains the values.
Normally the `read` call is written this way in PySimpleGUI:
This unpacks the tuple in to 2 variables, `event`, representing the event that caused the `read` to return, and `values`, the dictionary containing all of the values in the input fields for the window.
Recall earlier in the Queue example I said the `Queue.get` model would be seen again. You just saw it in the `window.read()` call. The default action is to block on that `read`. Just like `Queue.get()` you can put a timeout value on the call so that the block will end after the timeout and return back to you.
Here is how you can get a window's events in the same block with a timeout way. In this example, the `timeout` of 100 means "block for up to 100 ms" for an event to take place, then return.
If you want a function to be called when a button is pressed in your window, then you quite simply see if the event you received is that button and then YOU make the call.
```python
event, values = window.read()
if event == 'My Button': # if the button was clicked then
my_callback('My Button', values, ....) # make your callback
Experience has shown, however, that these "callbacks" are not used by most people using PySimpleGUI. Often the event is handled right on the spot, especially if the action to take is short and simple.
## The Fun Begins - Applying Python's Capabilities with GUIs
Since we're storing our window's GUI layout in a Python list, that means we can do fun Pythony things to create these layouts. One such activity is utilizing List Comprehensions to generate a layout.
```python
from PySimpleGUI import Text, CBox, Input, Button, Window
If you've tried Python GUI programming and gave up, or if you like what you see proposed here, then you can experience this kind of Python GUI development today. PySimpleGUI has been out for a little over a year and will "render" your GUI window **using** any of the big 3 GUI packages as the backend as well as being able to show your window in a browser by using Remi as the backend.
The super-simple examples shown in this article are just that, super-simple examples. The "Simple" of PySimpleGUI does not describe the problem space, but rather the difficultly in solving your GUI problems. Not many people would describe this PySimpleGUI Download Manager application as a "simple" program.
So try GUI building in Python in a completely different way than you may have tried in the past. A way that takes advantage of Python's unique syntax, types, and features that make it the magic language it is. Hop on over to http://www.PySimpleGUI.org and get started having fun building GUIs.