The Python PySimpleGUI project has two main goals:
- A simpler method for creating graphical interfaces, and
- Common code for Tkinter, QT, xW and Web graphics
I feel comfortable doing my own Tkinter and Web interfaces, but common code for both is very cool and it could be very useful for Rasp Pi applications. However things didn’t work “out of the box”, so this blog will look at some workarounds and issues.
A Simple Example
If you are used to coding in QT or xW PySimple is absolutely easier to use.
PySimpleGUI has some defined graphic objects (like Text or Button) and the screen placement is defined by how they are grouped with [ ] brackets. For example two objects in a [ ] bracket puts the two objects on the same line.
If you’re a Tkinter user PySimpleGUI may seem a little more cumbersome in it’s layout design. (I find Tkinter’s grid methods to be a superior layout approach).
For my first example I used the published example and I added an option for the graphic method (tkinter, Qt, Wx and Web):
import sys, random, time mode = "tkinter" # Check for command line arguments if len(sys.argv) > 1: # if there is use the Web Interface if sys.argv == 'web': import PySimpleGUIWeb as sg mode = "Web" elif sys.argv == 'wx': import PySimpleGUIWx as sg mode = "Wx" elif sys.argv == 'qt': import PySimpleGUIQt as sg mode = "Qt" else: import PySimpleGUI as sg else: # if no arguments use the standard GUI import PySimpleGUI as sg # Basic example from PySimpleGUI sg.change_look_and_feel('DarkAmber') # Add a touch of color # All the stuff inside your window. layout = [ [sg.Text('Some text on Row 1')], [sg.Text('Enter something on Row 2'), sg.InputText()], [sg.Button('Ok'), sg.Button('Cancel')] ] # Create the Window window = sg.Window('PySimpleGUI ' + mode , layout) # Event Loop to process "events" and get the "values" of the inputs while True: event, values = window.read() if event in (None, 'Cancel'): # if user closes window or clicks cancel break print('You entered ', values) window.close() print('Program terminating normally')
The output for the different graphic methods looks incredibly similar for this example:
It’s important to note that PySimpleGUI is still under development so many of the features will be in transition. If you stick to basic functions like: buttons, images and text you should be good.
I found that the default Tkinter version to be very solid, and the other versions would complain on some of the added features such as: frames, sliders, and progressbars.
A Realtime Update Example
For my next example I wanted to do a Rasp Pi type example with some simulated values from a temperature sensor.
To write back to a graphic object:
- define a key name when the object is defined (key = “myojbname”)
- use: window[‘myojbname’]( new_value) to update the object
import sys, random, time mode = "tkinter" # Check for command line arguments if len(sys.argv) > 1: # if there is use the Web Interface if sys.argv == 'web': import PySimpleGUIWeb as sg mode = "Web" elif sys.argv == 'wx': import PySimpleGUIWx as sg mode = "Wx" elif sys.argv == 'qt': import PySimpleGUIQt as sg mode = "Qt" else: import PySimpleGUI as sg else: # if no arguments use the standard GUI import PySimpleGUI as sg # Basic example of PSGWeb def main(): sg.change_look_and_feel('LightGrey') dataframe = [ [sg.Text('Temperature (C):',size=(12,2)), sg.Text(' ', font='Courier 48', text_color='red', key='degC')], [sg.Text('Humidity (%) :',size=(12,2)), sg.Text(' ', font='Courier 48', text_color='red', key='humid')], ] layout = [ [sg.Image(filename = "dht11.png"),sg.Frame("DHT11 Sensor", dataframe,font='Any 12', title_color='blue')] ] if mode == "web": # Note: customization on the Web interface window = sg.Window('Pi Weather Data ' + mode, layout,web_ip='192.168.0.107', web_port = 8888, web_start_browser=False, disable_close=True) else: window = sg.Window('Pi Weather Data ' + mode, layout) while True: event, values = window.read(timeout=10) temp_degC = random.randint(20,30) humidity = random.randint(0,100) window['degC']( temp_degC) window['humid'](humidity) time.sleep(1) window.close() main() print('Program terminating normally')
The Wx code would not run, and the development team has commented on compatibility issues that they are having with Wx so future support may be dropped.
The Tkinter and Qt, but for this example the Web presentation dropped the frame outline.
One big difference that I found between the Remi project and PySimpleGUIWeb is that Remi supports callbacks. I found that callbacks are extremely useful if you are trying to mix reads and writes in the same application. PySimpleGUI uses a read to get user input but this gets confusing if you are using a timer for writing new data to the GUI.
The PySimpleGUIWeb library by default was missing some key documentation. I found that “out of the box” it wasn’t usable for my applications . However everything that I needed was in the Window class it just wasn’t clearly documented.
The following web features can be controlled:
- web_ip=’xx.xx.xx.xx’ , default is localhost (127.0.0.1), not good for remote connections.
- web_port= xxxx , default is a random port id. Again not useful for remote connections.
- web_start_browser=False, default a web browser is launched (not useful for SSH).
- disable_close=True , default closes the app when the web browser closes.
An example to open a Web connection (not local) that doesn’t auto-open a browser and stays open would be:
window = sg.Window('Pi Weather Data ', layout,web_ip='192.168.0.107', web_port = 8888, web_start_browser=False, disable_close=True)
I like the concept of the same code being used on both a Tkinter and a Web app. I believe that this has a lot of potential. However at this point only the simplest features are available in the Web, so I’d rather use a Python Web framework like Bottle.
I really like some of the concepts of PySimpleGUI but I think that understanding and using the standard Tkinter allows you more flexibility and it lets you include add-in modules like Tk_tools.