|
Handling User Input
The Input-Process-Output (IPO) model provides a basic concept of how computer works. To demonstrate the model, it is common to write short programs that opens a modal dialog with a single text field and an OK/Cancel button pair. When the OK button is hit, the dialog closes and the input data is processed by some simple algorithm. The result considered as output is displayed in another window (e.g. an message box or a console).
Python has a built-in function raw_input() to request user input from the console. TigerJython adds some convenient functions to read data from a modal input dialog. input() opens a dialog and the return value has the data type of the entry, either an int, a long, a float or a string. When the Cancel or the close button is hit, the program terminates.
If a particular input data type is requested, inputInt(), inputFloat() or inputString() can be used. If the entry does not correspond to the requested type the dialog is redisplayed with an error message. (For inputFloat() an integer entry is converted to a float).
Select InputEx2.py (Ctrl+C to copy, Ctrl+V to paste)
To prevent the program to terminate when the Cancel or close button is hit, inputString() takes a boolean parameter. When False is passed, the function returns None instead of terminating. By checking the return value for None it is possible to implement a user definable action, when the Cancel or close button is hit.
Select InputEx3.py (Ctrl+C to copy, Ctrl+V to paste)
To enter a boolean value, askYesNo() can be used. If the Yes button is hit, True is returned, if the No button is hit, False is returned, if the Close button is hit, the program terminates unless the function is called with a second parameter False.
Select InputEx4.py (Ctrl+C to copy, Ctrl+V to paste)
If you intend to run your program standalone (without an OS console or an IDE), you should not use the print statement (unless you redirect stdout to a GUI console). To output a single line of text, call msgDlg() and a modal message box with an OK button is opened. The program continues when the OK or Close button is hit.
Select InputEx5.py (Ctrl+C to copy, Ctrl+V to paste)
Enumerations
To implement state-controlled algorithms (finite state machines, FSM), it is highly recommended to use literals to denominate the states (e.g. for a video player IDLE, PLAYING, PAUSED).
|
|
|
Video player modeled as a state machine
from "Programmieren mit Kara" (modified)
|
Unfortunately Pyhthon/Jython does not support the enum data type, but TigerJython adds full support for them. The following example shows how it is simple and straightforward to implement the above state diagram using TigerJython's enums.
# EnumEx1.py
from gpanel import *
State = enum("IDLE", "PLAYING", "PAUSED")
state = State.IDLE
createGPanel()
enableRepaint(False)
while True:
if kbhit():
ch = getKey()
if ch == "p" or ch == "P":
if state == State.IDLE:
state = State.PLAYING
elif state == State.PLAYING:
state = State.PAUSED
elif state == State.PAUSED:
state = State.PLAYING
if ch == "s" or ch == "S":
if state == State.IDLE:
state = State.IDLE
elif state == State.PLAYING:
state = State.IDLE
elif state == State.PAUSED:
state = State.IDLE
delay(1)
clear()
pos(0.5, 0.5)
circle(0.1)
text(0.47, 0.49, str(state))
repaint()
| |
Select EnumEx1.py (Ctrl+C to copy, Ctrl+V to paste)
Discussion: The implementation of enums in Jython requires to use the constructor of class enum to denominate the different enum values as string arguments (The enums are not really strings as you may argue, but members auf a class JEnum). We violate the standard convention and use a capital for the class instance State in order to follow the usual naming convention for enums in other languages.
The state transitions are triggered by pressing the 'P' keyboard key (for Play/Pause) or the 'S' key (for Stop). We use the kbhit() method of the GPanel graphics library to detect a key press and the getKey() method to determine which key it was. This is the standard procedure if you do not want to halt the program while waiting for a key press.
In order to avoid flickering due to the fact that the screen is rendered when clear() is called, we disable the automatic rendering by calling enableRepaint(False) and invoke repaint() manually.
| |