Sunday, 1 October 2006

GUI programming basics 1/3

This is the first of three posts on the basics of GUI programming. This post covers the most fundamental of GUI concepts with some example code to illustrate them. The next post will cover some more complex issues (in particular, layout managers) and the final post in this series will contain an extended example -- a simple text editor.



GUI programming is a bit of a black art. It sits on the interface of prgramming and HCI and usually requires careful planning (for usability) and relatively, but not very, sophisiticated programming techniques (meaning we don't teach it in the first year). Generally, GUI toolkits make good use of objects and to learn a new toolkit you need to understand a whole bunch of GUI jargon. Conceptually, there's not a lot new to learn when it comes to writing GUIs. If you already know about objects, OOP and event loops then you've learned most of what you need, the rest is just jargon and libraries. So, first to the jargon, then we'll look at some code. The following is a brief glossary of GUI concepts, in alphabetical order:




Binding:

Binding is the process of associating an event (such as a key press or mouse movement) with a callback or event handler. For example, we might bind the key accelerator Ctrl-S with the callback onSave.


Callbacks (or Event Handlers):

A callback or event handler is a piece of code (usually a function or method) which is executed when an event occurs. For example, an callback called 'onQuit' may be run when the key accelerator Alt-F4 is pressed by the user. Note that callbacks are written by the GUI programmer but scheduled to run by the toolkit -- i.e. you don't usually have to write your own event loop!


Containers:

A container widget may have other widgets embedded within it. For example, a top-level container for an application may contain a menu, statusbar, toolbar and so on.


Events:

An event is usually some form of input or interaction that occurs externally to a GUI but can be detected by the GUI toolkit. Examples include keyboard key presses, mouse movements and button presses, drag'n'drop, and so on. Most events will be uninteresting (e.g. mouse movements) but some require a response from the GUI (such as button presses and key accelerators).


Event Loop:

A loop which is used to dispatch callbacks in response to events. Usually the event loop for a GUI is provided by the toolkit and doesn't need to be written from scratch.


Widgets:

A widget is a single element in a GUI and in OOP languages is usually an object. Example widget types are: label, button, text entry field, canvas (to display graphics), list box, scroll bar, radio button, etc.



Simple GUIs with Tkinter and Python



Tkinter is the cross-platform GUI toolkit which ships with Python. It's based on the Tcl/Tk system and it's popular because of it's simplicity. Other toolkits are a bit more sophisitcated (like, wxPython, based on the C++ toolkit wxWidgets) but are also more complex. So, Tkinter is a good place to start if you haven't writen GUIs before, but you might want to look around at other libraries when you're a bit more confident of the basics.



What follows is a very simple series of 'Hello World!' scripts which introduce the very basic concepts of GUI programming by producing minimal GUIs. The next post on GUI programming will introduce some more complex practical concerns -- various widget types, layout (geometry managers), and so on.



Hello World! (1)



This script is absolutely minimal. It simply creates an empty application window (called root) and instructs Tkinter to start it's event loop.




#!/bin/env python2.4

"""
Hello World! with Python's Tkinter GUI toolkit.
"""

from Tkinter import *

__author__ = 'Sarah Mount'
__date__ = 'October 2006'

root = Tk()
root.mainloop()



Hello World! (2)



An empty application window isn't much use! The next script creates a single widget, a label. Labels are holders for text. They generally don't do anything (unlike, say, buttons) so they are really the simplest widget around. In our case, we just want to create a label, pack it (meaning, arrange it on the main application window) and start the Tkinter event loop.




#!/bin/env python2.4

"""
Hello World! with Python's Tkinter GUI toolkit.
"""

from Tkinter import Label

__author__ = 'Sarah Mount'
__date__ = 'October 2006'

# Create a widget
widget = Label(None, text='Hello World!')
# Arrange widget in application window
widget.pack()
# Start GUI event loop
widget.mainloop()


Hello World! (3)



Our third version of Hello World! introduces callbacks. Here, we use a button widget rather than a label. When we create the button, we need to give Tkinter a reference to a function which can be called to handle mouse click events.




#!/bin/env python2.4

"""
Hello World! with Python's Tkinter GUI toolkit.
"""

from Tkinter import *
import sys

__author__ = 'Sarah Mount'
__date__ = 'October 2006'

def quit():
print 'Quitting...'
sys.exit()

widget = Button(None, text='Quit Hello World!', command=quit)
widget.pack()
widget.mainloop()


Hello World! (4)



This last script is essentially the same as the last, but makes use of a lambda expression in the callback. This is a common technique and although it's rather pointless in such a simple script, lambdas are a great way to cut down the size of your code whenever you need a simple function call in an event handler.




#!/bin/env python2.4

"""
Hello World! with Python's Tkinter GUI toolkit.
"""

from Tkinter import *
import sys

__author__ = 'Sarah Mount'
__date__ = 'October 2006'

def quit(msg):
print msg
sys.exit()

widget = Button(None, text='Quit Hello World!', command=lambda: quit('Quitting...'))
widget.pack()
widget.mainloop()


Further reading



No comments:

Post a Comment