top of page

UIs in Python with PySimpleGUI



I’ve tried so many UI libraries over the years that I usually start with a simple program to get a feel for the API, the script is a simple click counter that is the basis and framework for more advanced programs. In essence, you want to create a window, add a button, and have that button call a function which increments a counter, this counter is displayed and updated in the UI:



import PySimpleGUI as sg

# Some global constants and variables...
AppFont='Any 16'
sg.theme('DarkBlue3')
_VARS= {'clickCount': 0}

# The function that is going to be called, note how
# it selects the text field via a key...

def myFunction():
    _VARS['clickCount'] +=1
    window['-keyforText-'].update('Clicked: '
            +str(_VARS['clickCount']) +' times')
    print('called my Function')

# Here's where you set a layout and add UI widgets, note both
# the button function call and the text display key that matches the
# one on the previous function

layout= [[sg.Button('Click Me !', 
    key=lambda: myFunction(), 
    font=AppFont),sg.Exit(font=AppFont)],          
    [sg.Text('Not clicked yet', 
    key='-keyforText-',
    font=AppFont, size=(20, 4))]]

# Add everything under a window...

window=sg.Window('Window Title', layout)

# And finally add an event loop to catch events
# and behavior, pretty standard pattern

whilev True:             # Event Loop
    event, values=window.read()
    if event in (None, 'Exit'):
        break
    if callable(event):
        event()

window.close()

I cobbled the above from reading the documentation and a couple of SO questions, more thoughts on the documentation later. Something very cool that PySimpleGUI does is provide pre-coded buttons for common tasks ( in this case the exit button and event ), read more here: Button Element shortcuts.
You should get:

The hover state on my mac is a bit wonky, not sure what the issue is, but you could probably overwrite the theme.


Look and feel

Out of the box, PySimpleGUI has a blocky 90’s look that might or might not be of your liking, but all the basic widgets and controls are there. Here’s a sample of them, check this link for the code: Nearly All Elements with Color Theme, Menus, (The Everything Bagel)

It is pretty simple to change color themes and things like fonts and element size. I just wish the default elements/widgets had a more modern look ( like Bootstrap or Material Design over in JS land ). Making your own custom elements like a knob might be possible but is not immediately clear how, but on the plus side you can add your own button graphics and make your own themes.


To be fair GUI's in python suffer from not being able to separate presentation and logic/data due to the language nature, if you are coming from Javascript, Python would need a browser and CSS, KIVY ( another python GUI ) tries to do just this but at the cost of added complexity, and PyQt/PySide (the pro choice in GUIs) provides a more polished look and deeper control, but you guessed it it's more complex and has it's own set of quirks, PySimpleGUI seems like a good middle ground.


Layouts & Integrations

A very common use of GUIs in python is the orderly tiling of charts and other elements from external libraries, and this presents a good opportunity to test PySimpleGUI’s integration and layout capabilities. The spec here is to have a couple of stacked plots from matplotlib, a couple of buttons and a text box…


PySimpleGUI docs mention this, but it bears repeating. When you are doing GUIs for python or other languages, you usually start with a sketch, and once you know your GUI's API, you can be more specific, in this case we can at least organize the UI spec (left ) into 2 columns and rows we will need to add to our window via the layout ( right )...

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
importmatplotlib
matplotlib.use('TkAgg')
sg.theme('LightGrey1')

# matplotlib :
fig=plt.figure(figsize=(4, 4))
# plt rows cols undex
plt.subplot(2, 1, 1)
X1=np.random.randint(100, size=(10))
plt.plot(X1, color="black", marker="o", linestyle="solid")

plt.subplot(2, 1, 2)
X2=np.random.randint(100, size=(10))
plt.plot(X2, color="black", marker="o", linestyle="solid")
# Here you would normally use pyplots GUI..
# plt.show()

# HELPER CODE from
# https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib.py

def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', 
            expand=1)
    return figure_canvas_agg

# LAYOUT, precompose columns...
column_1= [[sg.Canvas(key='-CANVAS-')]]

column_2= [[sg.Button('Do Stuff', size=(14, 1))],            
            [sg.Button('Do Other Stuff', size=(14, 1))],            
            [sg.Text('Some text')]]

# Rows are added with a new [] declaration
# Note the pad argument for tweaking alignement
layout= [[sg.Column(column_1),
    sg.Column(column_2)],          
    [sg.Button('Save', pad=((40, 0), (0, 0))), 
    sg.Button('Exit')]]

# Create window
window=sg.Window('UI Integration', layout,finalize=True, font='Helvetica 18')

# add the plot to the window
fig_canvas_agg=draw_figure(window['-CANVAS-'].TKCanvas, fig)

event, values=window.read()
window.close()

Should give you:

You still need to wire the buttons/text to functions and events like in the first example.


Like other grid systems out there, you need to get comfortable with the syntax. PySimpleGui uses a mix of row [[row][row]] and column to place elements as well as some alignment options. As for integrations, I haven’t tried them all, but it seems to be somehow specific for each case. Consult the abundant examples from the docs to see if yours is already there, else you have a general canvas and event loops. For even more complex integrations you can use threads and other methods.


Documentation

Docs by content are top notch. You can browse or go deep into any one topic and the abundant code examples cover many cases. Unfortunately it is somehow hard to read due to how it is organized (could use pagination), just stick to it, it does gets better.

The problem here is that every time you need to consult the docs you need to load a big a** page and scroll scroll scroll, not fun.


Final thoughts & Recommendation

I liked my first time with PySimpleGui and intend to use it to prototype my next project. I can also see myself reaching for it when I need to deliver something quick or experiment and just need a functionally GUI, this covers maybe 80% of my day to day. I found 3 main drawbacks you might wish to consider : GUI style, Documentation and Code complexity (especially for complex integrations), but these might be non issues for you.


Couple of Alternatives: 

KIVY: If you need to target mobile, cross platform and want a modern looking GUI (very opinionated), docs are great but the learning curve is steep, very steep. Read my take 
here:
https://k3no.medium.com/kivy-menagerie-af6a53e74695

PyQT/PySides: Super polished look at the cost of a steep learning curve and complexity, some license issues, considered the Industry standard, not beginner friendly. Read my take here:
https://medium.com/swlh/python-gui-with-pyqt-pyside2-5cca38d739fa 

And that’s it, go on and make that awesome GUI in Python.



Source: Medium


The Tech Platform

0 comments
bottom of page