Cheatsheet¶
PyperCard is an easy and simple GUI framework with a focus on beginner Python programmers. This page contains all the technical information you need in one place. You should use it for reference purposes. If you’d like to learn more about PyperCard please consult the tutorials.
Installation¶
PyperCard runs on top of PyScript - a browser based Python platform.
The quickest way to get going is via a free (but limited) account at PyScript.com:
Create a new project.
Update the project’s
pyscript.tomlfile sopypercardis listed as a dependency:
packages = ["pypercard", ]
Create your app and define transitions, via Python, in the
main.pyfile.The
index.htmlfile can be used to define how your cards look via several hiddentemplateelements.
Alternatively, just look at the example projects to see how to organise an app.
Core concepts¶
PyperCard’s core concepts are:
An app contains a stack of cards.
A card represents a screen in your app.
A transition allows users to move between cards in a meaninful way.
If the app is the global context, then each card fulfils a specific role or function within the application. Cards define what the user sees at any given time.
When a transition is activated (for example, because a user has clicked a button), functions containing business logic are called, state is changed via the app’s key/value datastore (more on this below) and the next card is indicated.
The App¶
The App class represents a card based application.
This object encapsulates state (as a key/value DataStore instance), a stack
of Card instances, and registering transitions.
The app’s datastore is a shim around the browser’s localStorage expressed
as a Python dict. Sometimes, because of the browser’s security policy, it’s
not possible to get access to localStorage and so a standard Python dict is
used instead (although, as a result, state is not preserved between page
reloads).
For an app to work, it needs a stack of cards and some transitions. Each card
has a name, unique within the application context. A list of Card instances
can be passed in when the app is instantiated, or cards can be added later, on
the fly. If no cards are passed in at instantiation, the app will query the DOM
for template elements, whose attributes and content it will use to create its
stack.
Transitions are simply decorated Python functions that will be called with the
instance of the app, and the Card instance representing the card that
generated the event that fired the decorated transition function.
Other app-wide functions (such as playing or pausing sounds) are methods of this class. To add your own app-wide functions, create a sub-class of this one.
Once created, start the app with a given card, or else the app starts with the very first card added to its stack.
The application is rendered into the DOM via a pyper-app element.
A Card¶
A Card instance defines what is presented to the user. The app ensures only
one card is displayed at any time.
Every card has a name that is unique within the current application, and a
template that can either be a string passed in at instantiation time or else
the card will look for a template tag in the DOM with an id that matches
the card’s name, and whose content and attributes will define how the card
looks and behaves.
Cards may also have optional auto_advance and transition attributes for
transitioning to a target card after a given period of time.
Cards are rendered from the template in the show method. The first time
show is called it creates a pyper-card HTML element for the app to
insert into the DOM.
Bespoke behaviour for rendering can be defined by the user. This should
be passed in as the optional on_show argument when initialising the
card. It will be called, at the end of the card’s show function, but
before the element to insert into the DOM is returned to the app. The
on_show function is called with the same arguments as a transition
function: a reference to the app and the current card.
The hide method hides card’s HTML element, but leaves it in the DOM.
Card’s can optionally take some action each time a card is hidden using the
on_hide method. The on_hide method is called with the same arguments as
a transition function: a reference to the app and the current card.
The convenience functions called get_by_id, get_element and
get_elements return individual or groups of matching HTML elements
rendered by this card, given a valid id or CSS selector (comments attached
to the functions explain the specific behaviours).
Cards can optionally define the nature of their background, via the
background and background_repeat attributes. The background should
either be a valid CSS color or a URL to an image. If the background is
an image, the background_repeat flag will indicate if the image will
fill the whole screen or repeat in a tiled fashion (the default is to
fill the whole screen).
The attributes of a template element in the DOM will map directly to the
attributes of the related Card instance. Thus, background, auto-advance
and other HTMLElement attributes set the equivalent methods on the instance.
A further convenience includes detecting a transition attribute on an HTML
button element within the card’s template. If, when the card is visible to
the user, the button is clicked, it will automatically transition to the name
of the card given as the value of the transition attribute.
Transitions¶
Transitions are simply Python functions that react to events, and tell the app what to do next.
If a transition returns a string, and the string contains the name of a card in
the app’s stack, the app will hide the current card and display the card
referenced in the result of the function. If the transition function returns a
None the app will keep the current card on the screen.
A transition function always takes the same arguments, a reference to the
current app (so you have access to getting/setting state or other capabilities
provided by the App class), and the Card instance that dispatched the
event. You can, optionally, retrieve the event object created by the browser
that represents activity that resulted in the function call.
To define a transition function you need to use a decorator provided by your app.
my_app = App()
@my_app.transition("my_card", "click", "button_id")
def my_transition(app, card, event):
"""
A decorated transition function for the "my_card" card.
When the HTML element with the `id` "button_id" is "click"-ed then the
function will be called.
"""
... do business logic here...
return "next_card"
This just adds a transition to the app’s underlying state machine.
The first argument can be either a string of the name of the target card, or a list of target card names.
The second argument is the name of the event, as dispatched by the browser, e.g. “click”.
The third argument is the unique id attribute of the target element within
the referenced card[s], that will dispatch the event.
Finally, you can replace the id argument with a named query argument, as a
way to provide a valid CSS query to match elements within the referenced
card[s], that will dispatch the event.
DataStore¶
Every app has a datastore, an object that behaves like a Python dict for
storing app state.
Usually, this is a Pythonic shim around the browser’s localStorage object.
However, sometimes due to the browser’s security context, the localStorage
object is not available. In this case, a regular Python dict is used, but
with the disadvantage that state isn’t retained between page reloads.
For more information about the characteristics of the localStorage object
please
read this documentation.
Other Stuff¶
The PyperCard framework is very much “early stage” and alpha quality, despite such a lot having already been written.
More coming soon.