Wednesday, October 23, 2019

Mike Driscoll: 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”.


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 widgets
text = sg.Text("What's your name?")
text_entry = sg.InputText()
ok_btn = sg.Button('OK')
cancel_btn = sg.Button('Cancel')
layout = [[text, text_entry],
          [ok_btn, cancel_btn]]
 
# 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: Text, InputText and two Buttons. To layout the widgets in rows, you can add them to lists. So for the first row of widgets, you create a list that contains the Text widget followed by the InputText widget. The widgets are added from left-to-right horizontally. To add a second row, you add a second list of widgets, which contains the two buttons.

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

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 Widgets

There isn’t enough time to go over every widget that PySimpleGUI supports. However you can see which widgets 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.

This should get better if the developers behind PySimpleGUI can finish wrapping wxPython’s widgets or Qt’s as they both have robust table and tree widgets.


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 widgets
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 a GUI that uses a more Pythonic approach versus a C++ approach, 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 seems a bit small out of the box, but as they wrap other toolkits more this will be less of an issue. Frankly, they have a lot of cool demo applications on their Github as well as a demo application for the project itself. 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.

The post A Brief Intro to PySimpleGUI appeared first on The Mouse Vs. The Python.



from Planet Python
via read more

No comments:

Post a Comment

TestDriven.io: Working with Static and Media Files in Django

This article looks at how to work with static and media files in a Django project, locally and in production. from Planet Python via read...