Web Analytics Made Easy - Statcounter
Skip to content

The PySimpleGUI Architecture - Under The Hood

If you want to get a little deeper understanding of how PySimpleGUI differs from "traditional GUI libraries", this is the place.

First, understand that this section is a summary, a simplification, an overview of some other framework architectures, as well as an overview of the PySimpleGUI architecture. It's been simplified and there are generalizations, so there is no need to shout and point at your screen.

Definitions

Let's get some terms understood to make the descriptions go smoother.

Event - Something that happens. Can be a button click, an item chosen from a drop-down menu, a menu item chosen, a character typed... LOTS of events are possible in a GUI.

Callback - When a function you've written is called due to an event occurring.

Queue - A data structure in computer science. Like a list where items are added on the "input end" and taken out on the "output end". The result is the when a queue is "read", the items are taken out of the output end in the order they were put into the input end.

Message - "Some data". Could be a variable, a tuple, a string... what type it is doesn't matter."

User/Application Code - Python code that you write that's in your .py file(s).

Object Oriented GUI Development / "Event Driven" (Push Modal)

image

This is THE topic that trips up programmers trying to learn GUI development. The "problem" is that human being don't think in a highly "distributed" or fragmented way. This style of architecture consists of many small functions containing the code that will handle your "event".

Let's call this the "Push Model" because when an event happens, it's actively "pushed" at you. With these architectures, the application usually creates the GUI layout, and then as the last statement in the program calls a function like mainloop contained in the "window" class. In tkinter it's called mainloop. You'll often find tkinter examples that specifically read root.mainloop(). A search for root.mainloop on GitHub returned 486,000 results. This function does not return until the window is closed.

That last statement is important. Your code, is written linearly in your .py file, top to bottom, and at the end, you call a function that never returns until the window is closed.

What is this mainloop() function? I'm glad you asked! It's the "GUI Dispatcher". When you created your window, you created each widget such as Buttons. When you created each button, you told tkinter the name of the function to call for that button. This function is a "callback function".

The result is that you've got lots of these little functions that you wrote for each widget. Typically these functions are actually "methods" in a class. You'll make a class based on a tkinter Button, and in that class you'll have a method that you tell tkinter to call when that button is clicked.

Your code may look something like this for a GUI with 4 widgets - A Button, a Slider, an Entry (text input ), and another Button.

image

You'll have 4 classes and the code for those callback functions are going to be scattered inside one file or could be split across several files.

Stepping Through a Run

OK, we've got the stage set, let's run your code.

thumb_112

You've written the code for your classes, you've written the callback functions (usually as methods in the classes) and you've just called the mainloop() function.

At this point, the "GUI Library Dispatcher" is running. This is not code you ever see. It's not code in your program. The Dispatcher waits until something happens.

Your user clicks a button!

Ok, something's happened! In the "Push Model" architecture diagram the "Button Click" block at the top represents the button click happening. This causes some code in the blue "Dispatcher" box to run. That code determines which of your "Callback Functions" should be called when that button is clicked.

The Dispatcher then calls your callback function for that button.

Now your code is called. In the Push Model diagram, the code is shown as 3 boxes Button 1 Code, Button 2 Code, Button 3 Code.

If you look at the diagram with the classes you write, then you'll get a better idea of where this code is in your project. One of those green rectangles labeled with "Callback" is executed. Once you are finished doing whatever it is you need to do when the button is clicked, your function returns. When your function returned, the "GUI Dispatcher" takes over running again, waiting around for the next thing to happen.

"Callbacks" Can Be Confusing

notunderstand_112

Some programmers have no problem with their code being strewn all over the place. They're able to keep it in their heads, write their code in a specific way, organize their files in a way that adds some order to the chaos. This kind of a architecture is sometimes called "Event Driven".

The requirement to write classes for these various widgets or the application and placing callbacks inside them is one of the reasons beginners struggle to get over that GUI bar. Writing Python classes is not generally covered until the end of a course. It's not beginner stuff.

Widgets Manipulating Widgets

If classes and callbacks don't explode your head, let's toss in one more challenge. What if your button wants to do something to your slider? Maybe your button disables your slider. Now your button class needs to know something about your slider class.

frust_112

The PySimpleGUI Message Passing Architecture (Pull Model)

Before going through the PySimpleGUI architecture, let's look at one of Python's Standard Library constructs, the Queue. With a Python Queue, some message "arrives" and when it does, it's added to the end of the queue.

In the User's Code, the queue is "read", by calling the queue's get() method. The code would look something like this.

from queue import Queue

q = Queue()
item = q.get()

Don't worry about there being nothing added to the queue. The point is that the user asks for an item from the queue. The user calls get() and if there's an item in the queue, the item is returned.

image

You can think of the PySimpleGUI interface in exactly the same way. Your user code asks for an event. You are "pulling" items to processing out of the PySimpleGUI library. Contrast this to the "Callback" architecture where your code is directly called when an event happens.

image

In Computer Science, this type of interface is sometimes call "Message Passing". Instead of your code being directly invoked (called) you get a message passed to you by asking for one.

Asking For Events

Recall in the previous section that the code to get an event in PySimpleGUI is:

event, values = window.read()

Your call to window.read() is asking PySimpleGUI for the next event for you to process.

Event Loops

If you are going to keep reading events until the window is closed, then you put your window.read() call into a while loop:

while True:
    event, values = window.read()

This loop in PySimpleGUI is called the "Event Loop". The benefit to structuring code like this is that your processing of the events can be done linearly. Instead of small functions being scatters throughout your project, you've got your code that handles the events all in 1 place, and in a nice straight linear piece of code. For most people, this linear format is an easier way to visualize the problem than the distributed callback model.

image