Smarter event handling for PySimpleGUI
Project description
PySimpleGUI's Actions (PSGA) simplify event handling
install
python3 -mpip install psga
To run the demo, checkout the repository and install the required modules:
git clone https://github.com/aptly-io/psga.git
cd psga
python3 -mvenv .venv
. .venv/bin/activate
python3 -mpip install -e .
python3 -mpip install -e .[demo]
python demos/tabs_and_tables/main.py
Intro
PySimpleGUI is like the View in the Model-View-Controller paradigm. For less complex user interfaces, PySimpleGui's typical if-event then-action loop (that is a bit a Controller), works fine. However the event-loop's if-then-else becomes difficult to maintain for user interfaces with a large number of elements.
PSGA mitigates this by adding the following:
- The
@psga.action()
decorator turns a python method (or function) in anAction
. This action wraps both the handler and an event name (accessible through the propertyname
) to respectively handle and name the PySimpleGui event. Since VSC's intellisense recognizes thisname
property, are typo errors in the PySimpleGui'skey
less likely to happen. The optionalkeys
decorator parameter allows for additional keys that invoke the associated handler. - A
Controller
class groups and registers related handlers for processing user interaction and updating the corresponding view. This could hold your business/logic state. With aController
the source code becomes more maintainable and structured. - A
Dispatcher
class has a loop that reads the events from asg.Window
. Each event's value is then dispatched to the handler that was prior registered by itsController
('s). Manual registering is also possible (see the examples).
It is easy to gradually refactor existing source code with the PSGA feature.
Note that PySimpleGUI's documentation mentions it avoids concepts like call-backs, classes...
PSGA, with its action
and Controller
brings that back (so you might not like PSGA's concepts?).
Examples
All examples are sprinkled with comments to highlight PSGA's usage.
Grep for # PSGA:
to find these.
Hello world
PySimpleGUI shows the classic hello world in its Jump-Start section.
The source code below illustrates how PSGA could fit in this hello world example:
- Define a function that acts when the Ok button is clicked.
- Instantiate the dispatcher that will trigger the handler whenever the Ok event is fired.
Note that this simple example does not use a Controller
.
Note that the demos/hello_world.py
example usage PSGA in a slightly different way
(all roads lead to Rome).
import PySimpleGUI as sg
import psga
# PSGA: define an action for the Ok button
@psga.action(name="Ok")
def on_ok(values):
print('You entered ', values[0])
sg.theme('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('Exit'), sg.Button('Ok')] ]
# Create the Window
window = sg.Window('Window Title', layout)
# PSGA: initiate the dispatcher, register the handler and process the window's events
psga.Dispatcher().register(on_ok).loop(window)
window.close()
Example with a Controller
It shows PSGA's Controller
, action()
and Dispatcher
concepts
(without introducing any PySimpleGUI functionality).
from psga import Controller, Dispatcher, action
class _MyController(Controller):
answer = 0
@action(name="universal_question")
def on_ask(self, values):
"""with explicit name"""
_MyController.answer = values
@action()
def on_answer(self, values):
"""with implicit name"""
_MyController.answer = values
dispatcher = Dispatcher()
controller = _MyController(dispatcher)
dispatcher.dispatch("universal_question", 42)
assert controller.answer == 42
QUESTION = "What is the answer to the Ultimate Question of Life?"
dispatcher.dispatch(controller.on_answer.name, QUESTION)
assert controller.answer == QUESTION
Tabs and tables
The demo/tabs_and_tables
is a larger PySimpleGui example program.
It shows 2 sg.Tables
, each in a sg.Tab
, that get their data from a Model.
The model in turn uses REST requests to manage the data.
Right-click for the context menu that allows to add or delete table rows.
Notice how main.py
is kept lean and clean.
PSGA simplifies the event processing in a single line of code: dispatcher.loop(window)
.
Each functional program part is succintly grouped in its Controller.
For development
Following illustrates how to setup for PSGA development.
python3.11 -mvenv .venv
. .venv/bin/activate
# install module's dependencies
pip install -e .
# optionally install test features
pip install -e .[test]
# format, lint and test the code
isort demos tests src
black demos tests src
pylint src
pytest
# run the demos
export PYTHONPATH=src
python demos/hello_world.py
python demos/no_ui.py
python demos/tabs_and_tables/main.py
# build the wheel and upload to pypi.org (uses credentials in ~/.pypirc)
rm -rf dist/
python -m build
twine check --strict dist/*
twine upload dist/*
Note that on Mac OS one needs to install tkinter separately with brew:
brew install python-tk@3.11
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file psga-0.0.7.tar.gz
.
File metadata
- Download URL: psga-0.0.7.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d01f4e57bc91f39fb8c391e3ab2f69d3d8e27cbb1abf609df3f9623641bb8436 |
|
MD5 | 77631bd01943830252cbd48b91d4d726 |
|
BLAKE2b-256 | 87c1f4e50127c1b356498d2b4705d2119c754c59f7f083c49f5f01155d5a8da4 |
File details
Details for the file psga-0.0.7-py3-none-any.whl
.
File metadata
- Download URL: psga-0.0.7-py3-none-any.whl
- Upload date:
- Size: 6.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0dc8d27dc1cb4f75a267561663a3e784f4888e92873e9d484e1f295e2fdebea5 |
|
MD5 | d39505a357510cfd88ba34cbc4a331b8 |
|
BLAKE2b-256 | 4f1a4c7fd9538413ac01062041125fa42c5d6e30c85174fefc8f78bce4b7f0ce |