What makes Python good at GUIs?
♦ Rapid turnaround… easy to experiment
♦ Very high-level… fast to code GUIs
♦ Object-oriented… code reusability
♦ Dynamic reloading… changes without stopping
♦ Tkinter: simple code for simple GUIs
● Python’s OO interface to the portable Tk API
● Part of Python, lightweight, well documented, robust
● Meshes well with a scripting language: from Tcl
● Runs with native look-and-feel on X, MS-Windows, Macs
● Structure: [tT]kinter + Tk lib + (X, Windows, Mac libs)
● A de-facto standard: Tk used by Python, Perl, and TCL
● An open source system, supported/used by many
♦ wxPython: complex code for richer GUIs
● Second most popular GUI API for Python (or is it PyQt?)
● Portable GUI class library written in C++ (X, Windows, Mac)
● Wraps a C++ API: wxWidgets + wxPython
● Rich widget set: trees, html viewers, notebooks
● Tends to be more complex: C++ API (wx) verses scripting API (Tk)
● Was less documented, but wxPython book in 2006
● GUI builders: BoaConstructor, wxDesigner
● Tkinter + PMW package roughly as rich as wxPython?
♦ PyQt, PyGTK: on the order of wxPython
● From KDE & Gnome Linux libraries, but now portable
● PyQt third most popular GUI API for Python (?)
● PyQt: works on Sharp Zaurus PDAs, open source book
● PyQt: was not completely open source (but is today)
● Qt GUI builders: BlackAdder, QT Designer
● Example use case: free Calibre ebook viewer
♦ Jython (a.k.a. Jpython, originally)
● Access to Java GUI APIs: AWT, Swing, etc.
♦ IronPython .NET/Mono port
● .NET may provide GUI tools usable in Python scripts
♦ Rich Internet Applications (RIAs)
● Blurs line between “desktop” and web clients/GUIs
● Run in a web browser, javascript/ajax to be dynamic
● Gains browser portability at cost in software stack depth
● Pyjamas—now Pyjs (Py=>JS compiler, GWT toolkit), Silverlight (IronPython), Flex, etc.
♦ PyWin32 (former known as win32all)
● MFC integration for Python on Windows (only)
♦ PythonCard
● API + drag-and-drop builder on top of wxPython
♦ Dabo
● 3-tier application builder with GUI, Dbase, logic
♦ Anygui
● Portable API implemented on top of Tk, wx, Qt
See: Extras\Code\Gui\wxPython\wxPython.doc on CD for Tkinter,
wxPython comparisons
♦ Widgets: class instances
♦ Options: keyword arguments
♦ [tT]kinter exports classes and constants
♦ Widgets must be packed (or gridded,
placed)
♦ ‘mainloop’
shows widgets, catches events
♦ 3.X: ‘Tkinter’→‘tkinter’, supplemental modules renamed
file: gui1.py
from Tkinter import * # get widget classes
Label(text="Hello GUI world!").pack() # make a label
mainloop() # show, catch events
% python gui1.py
♦ Frames are widget containers
♦ Widgets attach to sides of a parent
♦ Event handlers are any callable object
♦ Button handlers are registered as ‘command’ options
file: gui2.py
from Tkinter import * # get widgets
def callback(): # define handler
print 'hello stdout world...'
top = Frame() # make a container
top.pack()
Label(top, text="Hello callback world").pack(side=TOP)
Button(top, text="press me",
command=callback).pack(side=BOTTOM)
top.mainloop()
% python gui2.py
hello stdout world...
hello stdout world...
Example: a live GUI demo
♦ Entry is a one-line input field
♦ lambda defers call to add an input argument
♦ showinfo is one of a set of common dialog calls
♦ Tk main window & Toplevel popups have icon, title
♦ + multi-line text, menus, radio/check buttons, dialogs,…
file: gui3.py
from Tkinter import *
from tkMessageBox import showinfo
def reply(name):
showinfo(title='Reply', message='Hello %s!' % name)
top = Tk()
top.title('Echo')
top.iconbitmap('py-blue-trans-out.ico')
Label(top, text="Enter your name:").pack(side=TOP)
ent = Entry(top)
ent.pack(side=TOP)
btn = Button(top, text="Submit",
command=(lambda: reply(ent.get())))
btn.pack(side=LEFT)
top.mainloop()
Other event interfaces
● widget.bind(“<B1-Motion>”, func) [CD bind.py]
● widget.after(msecs, func)
● slider/widget linkage, data stream conditions
GUI construction
● “What you build is what you get”
● Layout = build order + pack options
● Each Toplevel instance is a window
● Default Toplevel window if no parent
● Widgets nest in Frames, Frames nest in other Frames
● Object trees: Tkinter cross-links parents to children
“Decreasing Cavity Model”
► pack gives widget entire side
► widgets packed later get side of what’s left
► grid, place: alternative geometry managers
♦ Organization framework: namespace, inheritance
♦ Methods attach widgets to ‘self’
♦ Callbacks are bound methods of ‘self’
file: hello.py
#!/usr/local/bin/python
from Tkinter import * # get widgets
class Hello(Frame): # container subclass
def __init__(self, parent=None):
Frame.__init__(self, parent) # superclass init
self.pack()
self.make_widgets() # attach to self
def make_widgets(self):
widget = Button(self, text='Hello',
command=self.onPress)
widget.pack(side=LEFT)
def onPress(self):
print 'Hi.' # write to stdout
if __name__ == '__main__': Hello().mainloop()
% hello.py
Hi.
Hi.
♦ GUI classes can be extended by inheritance
♦ Subclasses may extend, or replace methods
♦ In OOP terms: a ‘is-a’ relationship
file: hellosub.py
#!/usr/local/bin/python
from hello import Hello # get superclass
from Tkinter import * # get Tkinter widgets
class HelloExtender(Hello): # is-a hello.Hello
def make_widgets(self): # extend method
Hello.make_widgets(self)
mine = Button(self, text='Extend',
command=self.quit)
mine.pack(side=RIGHT)
def onPress(self):
print 'Greetings!' # replace method
if __name__ == '__main__': HelloExtender().mainloop()
% python hellosub.py
Greetings!
Greetings!
♦ Frames can be attached to other Frames
♦ Tkinter records object tree internally
♦ In OOP terms: a ‘has-a’ relationship
file: hellouse.py
#!/usr/local/bin/python
from hello import Hello # get class to attach
from Tkinter import * # get Tkinter widgets
class HelloContainer(Frame): # has-a hello.Hello
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
self.make_widgets()
def make_widgets(self):
mine = Button(self, text='Attach',
command=self.quit)
mine.pack(side=LEFT)
Hello(self) # attach a Hello to me
if __name__ == '__main__': HelloContainer().mainloop()
% hellouse.py
Hi.
Hi.
See “Extras\Code\Gui\Code”
directory on class CD to run this
example
As of Python 3.4, tkinter supports PNG,
GIF, amd PPM/PPG; install Pillow for others
from Tkinter import * # get base widget set
from glob import glob # file name expansion
import hellouseCheck # attach the last example to "me"
import random # pick a picture at random
gifdir = '../../../Part3/Gui/gifs/' # where to look for gif files
def draw():
name, photo = random.choice(images)
lbl.config(text=name)
pix.config(image=photo)
root=Tk()
lbl = Label(root, text="none", bg='blue', fg='red')
pix = Button(root, text="Press me", command=draw, bg='white')
lbl.pack(fill=BOTH)
pix.pack(pady=10)
hellouseCheck.HelloContainer(root, relief=SUNKEN, bd=2).pack(fill=BOTH)
files = glob(gifdir + "*.gif")
images = map(lambda x: (x, PhotoImage(file=x)), files)
print files
root.mainloop()
# 2d table of input fields
# see also frigcal’s uniform gridding: tables
from Tkinter import *
rows = []
for i in range(5):
cols = []
for j in range(4):
e = Entry(relief=RIDGE)
e.grid(row=i, column=j, sticky=NSEW)
e.insert(END, '%d.%d' % (i, j))
cols.append(e)
rows.append(cols)
def onPress():
for row in rows:
for col in row:
print col.get(),
Button(text='Fetch', command=onPress).grid()
mainloop()
(Some
of the following may be in 2.X form: convert to run on 3.X)
See Extras\Code\Gui\Code to run this example
See Extras\Code\Gui\Code to run this example
See Extras\Code\Gui\Code to run this example
See Extras\Code\Gui\Code to run this example
See learning-python.com/gadgets for more sceenshots
See CD’s top-level Extras\PP4E-Examples folder for code
Also available at http://learning-python.com/books/about-pp4e.html
See CD’s top-level Extras\frigcal-mergeall folder
Click images below for larger versions on the web
♦ Portability
● [tT]kinter programs run with native look-and-feel on X,
MS-Windows, Macintosh
● Vast majority of code runs
unchanged across different platforms
● But some aspects are platform-specific,
especially window manager context (icons, modal dialogs)
♦ Other GUI widgets
● 25 widgets + dialogs, etc,: Text, Canvas, Listbox, Scrollbar, Image, Menu, Entry, Radiobutton,
Checkbutton, Scale,…
♦ Other Tkinter tools
● File handlers, scheduled
events, “grid” manager, drag-and-drop, tix and themes
● Pmw (Python Mega Widgets), PIL
(imaging), etc.; see Vaults site
● Interactive GUI builders: PythonWorks?, ActiveState Komodo
● BoaConstructor, BlackAdder
Gui buildes for wxPython, PyQt
♦ Implementation structure
● Tk + C extension module +
Python wrapper classes module
● Uses extending (Tk
lib) plus embedding (route events to handlers)
♦ Documentation
● “Programming Python 2nd
Edition”, Part II, 250 pages
● “Programming Python 3rd
Edition”, Part II, 300 pages
● “Programming Python 4th
Edition”, Part III 400 pages, + other parts: email client
● Other books: Manning book
(somewhat dated), and others (see Amazon)
● Tcl/Tk
books and manuals also provide basic widget docs
●
Tutorial,
reference: http://effbot.org/tkinterbook/
●
Reference: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html
●
Wiki: https://wiki.python.org/moin/TkInter
♦ Other links
Extras\Code\Gui\wxPython\wxPython.doc (Tkinter/wxPython comparison)
Extras\Code\Gui\Code
(additional Tkinter examples)
Extras\PP3E-Examples (book GUI examples,
Python 2.X)
Extras\PP4E-Examples (book GUI examples,
Python 3.X)
See Also:
Extras\PP4E-Examples → PP4E-Examples-1.4\Examples\PP4E\Launch_PyDemos.pyw
[tT]kinter book examples in class package (or use PP3E-Examples directory for Python 2.X)
Click here to go to
lab exercises
Click here to go to
exercise solutions
Click here to go to
solution source files
Click here to go to
lecture example files