PC204 Lecture 9

Conrad Huang

conrad@cgl.ucsf.edu

Genentech Hall, N453A

Topics

  • Homework review
  • Interactive programs vs. scripts
  • tkinter - Python graphical user interface toolkit
  • Pmw - Python megawidgets
  • Debugging suggestions

Homework Review

  • 8.1 - poker probabilities
  • 8.2 - short project description

Interactive Programs vs. Scripts

  • “Script” is an application where the programmer determines the order of execution from beginning to end.
    • Applications may need user input and still be scripts, e.g., they may ask the user to type some input at a particular point of execution.
  • “Interactive program” is a program where the user determines the order of execution from input using either:
    • a command line interface (CLI), or
    • a graphical user interface (GUI, pronounced goo-ey).

Interactive Program Pattern

    for line in sys.stdin:
        args = line.strip().split()
        if not args:
            # skip blank lines
            continue
        if args[0] == “cmd1”:
            cmd1(args[1:])
        elif args[0] == “cmd2”:
            cmd2(args[1:])
        else:
            print “unknown command:”, args[0]
    
  • The mark of an interactive program is an event dispatch loop.
  • For a CLI program, it looks something like this.

Event Loop and Event Dispatch

    cli.py

    # Registry of commands
    _registry = {}
    
    def register(function):
        """Add command to registry."""
        _registry[function.__name__] = function
    
    def mainloop(prompt="> "):
        """Run event loop."""
        import sys
        while True:
            sys.stdout.write(prompt)
            line = sys.stdin.readline()
            if not line:
                # terminate on end of input
                break
            args = line.strip().split()
            if not args:
                # ignore empty lines
                continue
            ambiguous = False
            f = None
            # look for command prefix in registry
            for k in _registry.keys():
                if k.startswith(args[0]):
                    if f is not None:
                        ambiguous = True
                        break
                    f = _registry[k]
            if ambiguous:
                print ("Error: %s is an "
                      "ambiguous command" % args[0])
            elif f is None:
                print ("Error: %s is an "
                      "unknown command" % args[0])
            else:
                if not f(args[1:]):
                    break
    
  • The loop that reads user input (in this case, the while loop reading from sys.stdin) is called an event loop because it waits for user events.
  • The event loop dispatches user input to functions based on input values.
  • The event loop and dispatcher may be abstracted into a simple command line interface module.

Using the cli Module

    usecli.py

    def test(args):
        print "test", args
        return True
    
    def tilt(args):
        print "tilt", args
        return True
    
    def verify(args):
        print "verify", args
        return True
    
    def quit(args):
        print "quit"
        return False
    
    import cli
    cli.register(test)
    cli.register(tilt)
    cli.register(verify)
    cli.register(quit)
    cli.mainloop()
    print "Returned from command loop"
    
  • Here is an example of how to use the cli module:
    • Define functions that handle events (callback functions),
    • Register functions with cli module, and
    • Enter the cli module event loop.
  • The callback functions are invoked by the event loop as needed.
    • You call the event loop and it calls back to your function.
  • The cli module may be reused for many scripts.
  • The standard Python module, cmd, is another variation on this theme.

Libraries and Frameworks

  • Library functions are called by user code to perform some tasks and return after the tasks are completed.
  • cli.mainloop() is somewhat different from most library functions in that it calls back to user-registered functions before returning.
  • A library that defines most functionality but allows callers to plug in their own code that gets called at predefined times is often called a framework.

Libraries and Frameworks

  • Most programs using a GUI framework follows the same form as our usecli.py program:
    • define callback functions,
    • define user interface elements, aka widgets,
    • register callback functions, and
    • enter GUI event loop.
  • Implementation-wise, you need to design your user interface before you know what callback functions you need to make the program work.

tkinter

  • tkinter is a GUI framework.
  • Common widgets in tkinter include:
    • Label – widget for displaying some text.
    • Button – push button that user may press.
    • Entry – input widget where user may type.
    • Canvas – graphical drawing area.
    • Frame – placeholder to control placement of widgets.
  • A callback may be registered for widget actions, e.g., invoke callback when a Button widget is pushed.
  • A function may also be registered for widget events, e.g., call function mouse moves over an Entry widget.

Basic tkinter Widgets

Canvas and Text Widgets

More TKinter Widgets

  • tkinter offers many more widgets:
    • Some are simple, e.g., Checkbutton and Scale.
    • Some are complex, e.g., Scrollbar and Menubutton.
  • For more complete documentation on tkinter widgets, see An Introduction to Tkinter by Fredrik Lundh. Although the guide was written for Python 2, most examples can be made to work with Python 3 by renaming packages, e.g., see Six: Python 2 and 3 Compatibility Library.

Python megawidgets

  • tkinter is a low-level interface that offers a lot of flexibility, but you have to write a lot of code.
  • Libraries built on top of tkinter offer more functionality with less programming.
    • For example, managing scrollbars for Canvas or Text widgets is possible with tkinter, but painful.
  • Python megawidgets (Pmw) is layered on top of tkinter and implements high(er)-level widgets such as ScrolledCanvas and NoteBook.

Pmw

  • Pmw is a Python package containing a number of “megawidgets” that are composed of basic tkinter widgets.
  • To use Pmw, you need to install the package using pip:
    • Run the following in a shell (on Linux or macOS) or command prompt (on Windows):
      python3 -m pip install Pmw
    • If you encounter permission problems, try to install only for your account rather than all users:
      python3 -m pip install --user Pmw

An Aside on Packages

  • A Python package is a folder of related Python modules.
    • A Python package folder must contain a file named __init__.py, which:
      • tells Python the folder is not a random collection of .py files, and
      • is executed when the package is imported.
    • All other .py files in the folder are considered modules of the package and may be imported with:
      • import package_name.module_name
  • Pmw uses some serious Python magic for its package management, so I usually just follow the recipes in the excellent documentation.

Pmw Example

  • pmw_scrolledcanvas.py
    • Displays a canvas with attached scrollbars.
    • Uses menu buttons for setting scollbar modes.
    • Uses a button box to show an array of aligned buttons.
    • Is written in ~100 lines of code.

Beyond tkinter and Pmw

  • tkinter and Pmw together provide a usable set of tools for building graphical user interfaces.
  • There are other (better?) ways to construct GUIs:
    • WYSIWYG interface design tools.
    • More comprehensive widget sets.
  • A lot of applications are migrating to a client-server model that uses a web browser as a graphical front end.
    • Client (browser) side is written in HTML5 and Javascript.
    • Server side is written in a variety of languages, including Python, PHP, Perl, …

Debugging

  • Don't guess.
    • Collect data on where the error is occurring.
      • Read the traceback.
      • Add invariant, pre- and post-condition checks.
      • Use print statements.
    • Change one thing at a time
  • Don't get discouraged.
    • No, the computer is not out to get you.
    • Explain the code to someone (perhaps yourself).
    • Take a break.
      • Don't work until you can't keep your eyes open.

Homework

  • 9.1 - Write a “gomoku” program. (An example from this lecture should be helpful.)
  • 9.2 - Write a description for your final project, including inputs, outputs, operations, what classes you plan to use, etc. (See Final Project Requirements for more information.)