
- •Introduction
- •Introduction - What, Why, Who etc.
- •Why am I writing this?
- •What will I cover
- •Who should read it?
- •Why Python?
- •Other resources
- •Concepts
- •What do I need?
- •Generally
- •Python
- •QBASIC
- •What is Programming?
- •Back to BASICs
- •Let me say that again
- •A little history
- •The common features of all programs
- •Let's clear up some terminology
- •The structure of a program
- •Batch programs
- •Event driven programs
- •Getting Started
- •A word about error messages
- •The Basics
- •Simple Sequences
- •>>> print 'Hello there!'
- •>>>print 6 + 5
- •>>>print 'The total is: ', 23+45
- •>>>import sys
- •>>>sys.exit()
- •Using Tcl
- •And BASIC too...
- •The Raw Materials
- •Introduction
- •Data
- •Variables
- •Primitive Data Types
- •Character Strings
- •String Operators
- •String operators
- •BASIC String Variables
- •Tcl Strings
- •Integers
- •Arithmetic Operators
- •Arithmetic and Bitwise Operators
- •BASIC Integers
- •Tcl Numbers
- •Real Numbers
- •Complex or Imaginary Numbers
- •Boolean Values - True and False
- •Boolean (or Logical) Operators
- •Collections
- •Python Collections
- •List
- •List operations
- •Tcl Lists
- •Tuple
- •Dictionary or Hash
- •Other Collection Types
- •Array or Vector
- •Stack
- •Queue
- •Files
- •Dates and Times
- •Complex/User Defined
- •Accessing Complex Types
- •User Defined Operators
- •Python Specific Operators
- •More information on the Address example
- •More Sequences and Other Things
- •The joy of being IDLE
- •A quick comment
- •Sequences using variables
- •Order matters
- •A Multiplication Table
- •Looping - Or the art of repeating oneself!
- •FOR Loops
- •Here's the same loop in BASIC:
- •WHILE Loops
- •More Flexible Loops
- •Looping the loop
- •Other loops
- •Coding Style
- •Comments
- •Version history information
- •Commenting out redundant code
- •Documentation strings
- •Indentation
- •Variable Names
- •Modular Programming
- •Conversing with the user
- •>>> print raw_input("Type something: ")
- •BASIC INPUT
- •Reading input in Tcl
- •A word about stdin and stdout
- •Command Line Parameters
- •Tcl's Command line
- •And BASIC
- •Decisions, Decisions
- •The if statement
- •Boolean Expressions
- •Tcl branches
- •Case statements
- •Modular Programming
- •What's a Module?
- •Using Functions
- •BASIC: MID$(str$,n,m)
- •BASIC: ENVIRON$(str$)
- •Tcl: llength L
- •Python: pow(x,y)
- •Python: dir(m)
- •Using Modules
- •Other modules and what they contain
- •Tcl Functions
- •A Word of Caution
- •Creating our own modules
- •Python Modules
- •Modules in BASIC and Tcl
- •Handling Files and Text
- •Files - Input and Output
- •Counting Words
- •BASIC and Tcl
- •BASIC Version
- •Tcl Version
- •Handling Errors
- •The Traditional Way
- •The Exceptional Way
- •Generating Errors
- •Tcl's Error Mechanism
- •BASIC Error Handling
- •Advanced Topics
- •Recursion
- •Note: This is a fairly advanced topic and for most applications you don't need to know anything about it. Occasionally, it is so useful that it is invaluable, so I present it here for your study. Just don't panic if it doesn't make sense stright away.
- •What is it?
- •Recursing over lists
- •Object Oriented Programming
- •What is it?
- •Data and Function - together
- •Defining Classes
- •Using Classes
- •Same thing, Different thing
- •Inheritance
- •The BankAccount class
- •The InterestAccount class
- •The ChargingAccount class
- •Testing our system
- •Namespaces
- •Introduction
- •Python's approach
- •And BASIC too
- •Event Driven Programming
- •Simulating an Event Loop
- •A GUI program
- •GUI Programming with Tkinter
- •GUI principles
- •A Tour of Some Common Widgets
- •>>> F = Frame(top)
- •>>>F.pack()
- •>>>lHello = Label(F, text="Hello world")
- •>>>lHello.pack()
- •>>> lHello.configure(text="Goodbye")
- •>>> lHello['text'] = "Hello again"
- •>>> F.master.title("Hello")
- •>>> bQuit = Button(F, text="Quit", command=F.quit)
- •>>>bQuit.pack()
- •>>>top.mainloop()
- •Exploring Layout
- •Controlling Appearance using Frames and the Packer
- •Adding more widgets
- •Binding events - from widgets to code
- •A Short Message
- •The Tcl view
- •Wrapping Applications as Objects
- •An alternative - wxPython
- •Functional Programming
- •What is Functional Programming?
- •How does Python do it?
- •map(aFunction, aSequence)
- •filter(aFunction, aSequence)
- •reduce(aFunction, aSequence)
- •lambda
- •Other constructs
- •Short Circuit evaluation
- •Conclusions
- •Other resources
- •Conclusions
- •A Case Study
- •Counting lines, words and characters
- •Counting sentences instead of lines
- •Turning it into a module
- •getCharGroups()
- •getPunctuation()
- •The final grammar module
- •Classes and objects
- •Text Document
- •HTML Document
- •Adding a GUI
- •Refactoring the Document Class
- •Designing a GUI
- •References
- •Books to read
- •Python
- •BASIC
- •General Programming
- •Object Oriented Programming
- •Other books worth reading are:
- •Web sites to visit
- •Languages
- •Python
- •BASIC
- •Other languages of interest
- •Programming in General
- •Object Oriented Programming
- •Projects to try
- •Topics for further study

The Tcl view
Since we've been comparing Python with Tcl throughout the early part of this tutor it seems sensible to show you what the early Label and Button example looks like in the original Tcl/Tk form:
Label .lHello -text "Hello World"
Button .bHello -text Quit -command "exit" wm title . Hello
pack .lHello .bHello
As you can see it is very concise. The widget heirarchy is formed by a naming convention with '.' as the top level widget. As is usual in Tcl the widgets are commands with the properties passed as arguments. Hopefully the translation of widget parameters to Python named arguments is fairly obvious. This means that you can use the Tcl/Tk documentation(of which there is a lot!) to help solve problems with Tkinter programming, mostly its an obvious translation.
That's as far as I'm going with Tcl/Tk here. Before we finish though I'll show you a common technique for bundling Tkinter GUI applications as objects.
Wrapping Applications as Objects
It's common when programming GUI's to wrap the entire application as a class. This begs the question, how do we fit the widgets of a Tkinter application into this class structure? There are two choices, we either decide to make the application itself as a subclass of a Tkinter Frame or have a member field store a reference to the top level window. The latter approach is the one most commonly used in other toolkits so that's the approach we'll use here. If you want to see the first approach in action go back and look at the example in the Event Driven Programming topic. (That example also illustrates the basic use of the incredibly versatile Tkinter Text widget)
I will convert the example above using an Entry field, a Clear button and a Quit button to an OO structure. First we create an Application class and within the constructor assemble the visual parts of the GUI.
We assign the resultant Frame to self.mainWindow, thus allowing other methods of the class access to the top level Frame. Other widgets that we may need to access (such as the Entry field) are likewise assigned to member variables of the Frame. Using this technique the event handlers become methods of the application class and all have access to any other data members of the application (although in this case there are none) through the self reference. This provides seamless integration of the GUI with the underlying application objects:
90

from Tkinter import *
class ClearApp:
def __init__(self, parent=0): self.mainWindow = Frame(parent)
#Create the entry widget self.entry = Entry(self.mainWindow) self.entry.insert(0,"Hello world") self.entry.pack(fill=X)
#now add the 2 buttons
#we use a nested frame pair to give a grooved effect fOuter = Frame(self.mainWindow, border=1, relief="sunken") fButtons = Frame(fOuter, border=1, relief="raised") bClear = Button(fButtons, text="Clear",
width=8, height=1, command=self.clearText) bQuit = Button(fButtons, text="Quit",
width=8, height=1, command=self.mainWindow.quit)
bClear.pack(side="left", padx=15, pady=1) bQuit.pack(side="right", padx=15, pady=1) fButtons.pack(fill=X) fOuter.pack(fill=X) self.mainWindow.pack()
# set the title self.mainWindow.master.title("Clear")
def clearText(self): self.entry.delete(0,END)
app = ClearApp() app.mainWindow.mainloop()
Here's the result:
The result looks remarkably like the previous incarnation although I have tweaked the lower frame to give it a nice grooved finish and I've supplied widths to the buttons to make them look more similar to the wxPython example below.
Of course its not just the main application that we can wrap up as an object. We could create a class based around a Frame containing a standard set of buttons and reuse that class in building dialog windows say. We could even create whole dialogs and use them across several projects. Or we can extend the capabilities of the standard widgets by subclassing them - maybe to create a button that changes colour depending on its state. This is what has been done with the Python Mega Widgets (PMW) which is an extension to Tkinter which you can download.
91
An alternative - wxPython
There are many other GUI toolkits available but one of the most popular is the wxPython toolkit which is, in turn, a wrapper for the C++ toolkit wxWindows. wxPython is much more typical than Tkinter of GUI toolkits in general. It also provides more standard functionality than Tk "out of the box" - things like tooltips, status bars etc which have to be hand crafted in Tkinter. We'll use wxWindows to recreate the simple "Hello World" Label and Button example above.
I won't go through this in detail, if you do want to know more about how wxPython works you will need to download the package from the wxPython website.
In general terms the toolkit defines a framework which allows us to create windows and populate them with controls and to bind methods to those controls. It is fully object oriented so you should use methods rather than functions. The example looks like this:
from wxPython.wx import *
# --- Define a custom Frame, this will become the main window ---
class HelloFrame(wxFrame):
def __init__(self, parent, ID, title, pos, size): wxFrame.__init__(self, parent, ID, title, pos, size)
#we need a panel to get the right background panel = wxPanel(self, -1)
#Now create the text and button widgets
self.tHello = wxTextCtrl(panel, -1, "Hello world", (3,3), (185,22))
button = wxButton(panel, 10, "Clear", (15, 32)) button = wxButton(panel, 20, "Quit", (100, 32))
# now bind the button to the handler EVT_BUTTON(self, 10, self.OnClear) EVT_BUTTON(self, 20, self.OnQuit)
# these are our event handlers def OnClear(self, event):
self.tHello.Clear()
def OnQuit(self, event): self.Destroy()
#--- Define the Application Object ---
#Note that all wxPython programs MUST define an
#application class derived from wxApp
class HelloApp(wxApp): def OnInit(self):
frame = HelloFrame(NULL, -1, "Hello", (200,50),(200,90) ) frame.Show(true)
# self.setTopWindow(frame) return true
# create instance and start the event loop HelloApp().MainLoop()
And it looks like this:
92

Points to note are the use of a naming convention for the methods that get called by the framework - OnXXXX. Also note the EVT_XXX functions to bind events to widgets - there is a whole family of these. wxPython has a vast array of widgets, far more than Tkinter, and with them you can build quite sophisticated GUIs. Unfortunately they tend to use a coordinate based placement scheme which becomes very tedious after a while. It is possible to use a scheme very similar to the Tkinter packer but its not so well documented. There is a commercial GUI builder available and hopefully someone will soon provide a free one too.
Incidentally it might be of interest to note that this and the very similar Tkinter example above have both got exactly the same number of lines of executable code - 21.
In conclusion, if you just want a quick GUI front end to a text based tool then Tkinter should meet your needs with minimal effort. If you want to build full featured cross platform GUI applications look more closely at wxPython.
Other toolkits include MFC, pyQt, pyGTK, the latter is Linux only at present although potentially could be ported to Windows too since the underlying GTK library already runs on Windows. Finally there is curses which is a kind of text based GUI! Many of the lessons we've learned with Tkinter apply to all of these toolkits but each has its own characteristics and foibles. Pick one, get to know it and enjoy the wacky world of GUI design.
That's enough for now. This wasn't meant to be a Tkinter reference page, just enough to get you started. See the Tkinter section of the Python web pages for links to other Tkinter resources.
There are also several books on using Tcl/Tk and at least one on Tkinter. I will however come back to Tkinter in the case study, where I illustrate one way of encapsulating a batch mode program in a GUI for improved usability.
93