A Brief Intro to PySimpleGUI

Creating graphical user interfaces (GUI) can be difficult. There are many different Python GUI toolkits to choose from. The top three that you are likely to see mentioned the most often are Tkinter, wxPython and PyQt (or PySide2). However there is a newer toolkit called PySimpleGUI that aims to make creating GUIs easier.

The way that PySimpleGUI gets its power is by being an abstraction layer on top of Tkinter, wxPython and PyQt. You can kind of think of PySimpleGUI as a wrapper. The developers behind PySimpleGUI have also recently added a 4th wrapper around Remi, which is a “GUI library for Python applications which transpiles an application’s interface into HTML to be rendered in a web browser”.

One of PySimpleGUI’s claims to fame is that you don’t need to use classes to create your user interfaces. This is an interesting way of doing things, but may turn off some users of the library.


Installing PySimpleGUI

Installing PySimpleGUI is a snap if you know how to use pip. Here’s the command you should run:

pip install pysimplegui

Note that this will install PySimpleGUI to your system Python. You may want to install it to a Virtual Python environment instead. You can use Python’s venv module to do that. Check it out!


Hello PySimpleGUI

When it comes to working with GUIs, it’s always easier to see how you might put one together yourself. Let’s write little form that takes a string and has two buttons: an OK button and an Cancel button.

This example is based on one from the PySimpleGUI User’s Manual:

import PySimpleGUI as sg

# Create some elements
layout = [[sg.Text("What's your name?"), sg.InputText()],
          [sg.Button('OK'), sg.Button('Cancel')]]

# Create the Window
window = sg.Window('Hello PySimpleGUI', layout)

# Create the event loop
while True:
    event, values = window.read()
    if event in (None, 'Cancel'):
        # User closed the Window or hit the Cancel button
        break
    print(f'Event: {event}')
    print(str(values))

window.close()

Here you import PySimpleGUI and then you create a series of widgets, which are known as “Elements” in PySimpleGUI: Text, InputText and two Buttons. To layout the Elements in rows, you can add them to lists. So for the first row of Elements, you create a list that contains the Text Element followed by the InputText Element. The Elements are added from left-to-right horizontally. To add a second row, you add a second list of Elements, which contains the two buttons.

After you have all your Elements in a nested set of lists, you can create the Window. This is the parent Element that contains all the other Elements. It has a title and accepts your nested list of Elements.

Finally you create an while loop and call the Window’s read() method to extract the events and values that the user has set. If the user presses the Cancel button or closes the Window, you catch that and break out of the loop. Otherwise you print out the event and any value the user has entered.

This is what the GUI should look like when you run your code:

Hello World with PySimpleGUI

Let’s say you enter the string “mike” in the text entry widget and then hit the OK button. You should see the following output in your terminal:


Event: OK
{0: 'mike'}

Wouldn’t it be nice if you could redirect stdout to a debug window in your GUI though? PySimpleGUI actually has an easy way to do that. All you need to do is update your print statement in the code above to the following:

sg.Print(f'Event: {event}')
sg.Print(str(values))

Now when you run the code and enter a string and press OK, you should see the following debug window:

PySimpleGUI debug


PySimpleGUI Elements

There isn’t enough time to go over every Element that PySimpleGUI supports. However you can see which Elements are supported by going to this part of the documentation. There is a note in the documentation that mentions that Table widget currently has issues. It is implied that the Tree widget is also problematic, but doesn’t really talk about why.

Note that PySimpleGUI has wrapped all the widgets available in Tkinter, so you do have a good number of widgets to work with. However the widgets in ttk are currently not supported.

Update: After speaking with the package’s maintainer, I was told that the Table and Tree Elements are actually working quite well.


Creating Multiple Windows

One thing that I see a lot of new programmers struggle with is opening multiple windows in their GUI toolkit of choice. Fortunately, PySimpleGUI has directions of how to do this clearly labeled. They actually have two different “design patterns” for doing this sort of thing.

For brevity, I’ll only show how to do two active windows:

import PySimpleGUI as sg

# Create some Elements
ok_btn = sg.Button('Open Second Window')
cancel_btn = sg.Button('Cancel')
layout = [[ok_btn, cancel_btn]]

# Create the first Window
window = sg.Window('Window 1', layout)

win2_active = False

# Create the event loop
while True:
    event1, values1 = window.read(timeout=100)

    if event1 in (None, 'Cancel'):
        # User closed the Window or hit the Cancel button
        break

    if not win2_active and event1 == 'Open Second Window':
        win2_active = True
        layout2 = [[sg.Text('Window 2')],
                   [sg.Button('Exit')]]

        window2 = sg.Window('Window 2', layout2)

    if win2_active:
        events2, values2 = window2.Read(timeout=100)
        if events2 is None or events2 == 'Exit':
            win2_active  = False
            window2.close()

window.close()

The first few lines are pretty similar to the first example in this article. This time around you will create the main application with only two buttons. One of the buttons is used for opening a second window while the other button is used for closing the program.

Next you set a flag, win2_active, to False and then start your “event loop”. Inside of the event loop, you check if to see if the user has pressed the “Open Second Window” button. If they have, then you open the second window and watch for its events too.

Personally I find this kind of clunky to work with. I think a lot of this could be improved by using some classes for the Windows and abstracting the main loop. I wouldn’t want to have to deal with creating a lot of windows using this kind of pattern as it looks like it would get very complex very quickly to me. But I haven’t used this package enough to know if there are already good workarounds for this.


Wrapping Up

PySimpleGUI is a neat library and I like that it tries to be a bit more “Pythonic” than wxPython and PyQt tend to be. Of course, if you are looking for another GUI toolkit that uses a more Pythonic approach versus a C++ approach that PyQt and wxPython use, you might want to check out Toga or Kivy.

Anyway, I think PySimpleGUI looks like it has a lot of interesting features. The widget set matches Tkinter and even goes a bit beyond it. PySimpleGUI also has a lot of cool demo applications on their Github. They also have information on turning your application into an executable on Windows and Mac using PyInstaller, which is something you don’t normally see in the documentation for a GUI toolkit.

If you are looking for a simple GUI toolkit, PySimpleGUI might be right up your alley.