Console & GUI faces¶
This page explains the two shapes a d/Python program can take: a console program that runs top to bottom, and a window program that opens a window and responds to events. By the end you will know which shape fits what you are building and how to write each one. d/OS calls these the program's two faces. A face is how the host launches a program, not a different dialect: the same types, functions, classes, imports, optimizer and compiled bytecode serve both.
| Face | Who drives | Input | Output | Lifetime |
|---|---|---|---|---|
| console | the module's top-level statements | input(), program arguments after --, host services |
print(), the exit status |
start → run → halt |
| window | d/OS, which delivers each event | key and pointer events in a standard form | drawing requests, retained widgets, the window title | WINDOW_OPEN → draw/event turns → WINDOW_CLOSE |
A console program¶
Top-level statements run in order. print writes to the shared console; input pauses the program until a line arrives; reaching the end of the file stops the program with status 0.
"""A console application using Python's ordinary entry-point guard."""
def main():
names = ["Ada", "Grace", "Guido"]
for index, name in enumerate(names, start=1):
print(f"{index}: Hello, {name}!")
if __name__ == "__main__":
main()
__name__ is "__main__" when the module is the one you launched, and also when a module imports __main__ explicitly; __doc__, __package__ and __spec__ exist when you refer to them. On the command line, everything after -- reaches the program through services such as dos.service("READ_ARGS"), described in Console Services.
A window program¶
A module becomes a window program by decorating functions with the shared handler names: WINDOW_OPEN, WINDOW_DRAW, WINDOW_RESIZE, WINDOW_CLOSE, ON_KEY, ON_POINTER, plus the names of the newer lifecycle states (lifecycle v2). If you leave out a required handler, the compiler fills in an empty one for you. The module's top-level code runs once per launch, before the open handler.
import dos
@dos.on("WINDOW_OPEN")
def opened():
dos.service("SET_TITLE", "Faces")
@dos.on("WINDOW_DRAW")
def draw():
dos.intent("GFX", "BEGIN_FRAME")
dos.intent("GFX", "FILL_RECT", 0, 0, 320, 200, 6371)
dos.intent("GFX", "DRAW_TEXT", 20, 30, "A window face", 1, -1, 6371)
dos.intent("GFX", "PRESENT")
@dos.on("WINDOW_RESIZE")
def resized(width, height):
dos.service("INVALIDATE")
@dos.on("WINDOW_CLOSE")
def closed():
pass
The resize handler receives a width and a height; a key handler receives a key code; a pointer handler receives x, y and a button mask (a number whose bits say which buttons are held). Declaring a resize handler is what makes the window resizable. d/OS owns the window's state and decides when input is delivered; your handler runs inside a short, bounded turn and returns.
Both faces¶
dos.app(console=True) lets a window module also be launched as a console program. A compiled program that offers both faces runs as a console program by default; dpython run --native chooses its window face instead, whether you are running source or a .dbc file.
Which one, when¶
| Shape | A good fit |
|---|---|
| interactive console | lessons, small tools, calculators, text adventures, anything that has a conversation with the user |
| console script | reports, conversions, tests, the conformance test programs themselves |
| window program | editors, dashboards, games, long-lived applications, interfaces built from retained widgets |
The console is not the beginner mode, and the window is not a second language. Ask and Answer continues the console story; Windows & Events continues the window one.