There are lots of ways you can use Tkinter, the built-in graphical user interface library in Python, to create applications. I'm sure that a true Python expert would give different advice from what you read here. This guide is designed to be relatively simple, and, insofar as Tkinter permits this, to promote good programming practices. My guiding principle has been to keep the logic of the application completely independent of the graphical user interface.
Even though this is a very brief document about Tkinter, it
contains more information than I want you to keep in you
head! This really is a cookbook: copying the recipe
and changing a few ingredients will take you a long way.
The template has four parts:
Not every part will appear in every GUI program.
Applications that only use drawing and do not involve
buttons, like the happyface.py program with which the course
began, do not require an event handler.
Begin the program with
from tkinter import *
and then import whatever other libraries are needed. In our
examples, we've imported random for
the random-number generator.
The basic logic of the application should be independent of the
graphical user interface. By that I mean that you should
literally be able to take the identical functions, drop them into
another application, and have them work.
This is illustrated in the GUI triangle example posted on the
course website--I just used the same area and distance functions
that we had developed for the original non-GUI version.
In some of our examples, the application-specific functions
actually drew something, so we could not avoid Tkinter-specific
graphical elements. But we still structure these as
def draw_checkerboard(can, )
We make the drawing canvas a parameter of the function instead of
using the name of the canvas defined in the main event loop.
By doing so, we can copy this function and paste it in a different
Tkinter application in which the canvas is called something else,
or in which there is more than one canvas.
We'll discuss this before the event handler, although in the
program itself, I suggest you put it after the event handler, at
the very end.
The main loop always begins with a line like
win = Tk()
and ends with
The name win is just an ordinary variable
name; you can call it what you want, it just has to be the same
name in both these statements.
In between, you create widgets and place them in the
window. Widgets include canvases, buttons, labels,
single-line and multi-line text-entry fields, and a lot of other
things that we will not see in this course. In all cases,
creation and placement of the widgets is a two-step process.
Creation of the widget always looks something like this:
this_new_button = Button(win,....)
The first argument to Button is the parent widget. Very
often this is the original window, but we can also place widgets
inside of other widgets. The other arguments specify
attributes of the widget (the size of a canvas, the text to appear
in the button, etc.)
There are several options for placing widgets in the window. I
suggest using the grid method of the widget:
which specifies the position of the widget in its parent (in the fourth row and the first column---row and column numbers are zero-based).
For Canvas, Entry and Label widgets, at least in the first few
applications we will make, you only have to do the creation and
placement. For Button widgets, you want them to do
something, and for this you need to link the button to a function
that will say what to do when the button is clicked. So you
will need to add a line:
Here button_handler is the name
of a function that you will supply (and you can call it something
else if you want). This tells Tkinter what function to call
whenever there is a click of the left mouse button. In our
applications, we will only use these 'event handlers' for button
widgets. By the way, 'Button-1' refers to the left button on
the mouse, not the button widgets you are creating. The next
section explains the event handler.
Where can you go to read about the many different kinds of
widgets and the many, many different methods they support? I
have found the documentation at this
link and this one
to be most useful. But be careful! These documents were
written a long time ago, with Python 2 in mind, and some things
have changed. The biggest thing is that first line, from tkinter import *, which in Python 2
had upper-case 'T' instead of lower-case 't'. But as a reference
for what each of the individual widgets dows, I found these still
accurate, and indispensable.
The event handler is the glue that attaches the graphical user
interface to the application logic. In our template, it
responds to clicks in button widgets and calls the
application-specific functions. The event handler has access
to the global names of the widgets created in the main application
loop, one of the few instances in which we will use variables with
global scope. For instance, it may get the value of an
argument from an entry field, pass it to one of the
application-specific functions, and use the value returned to
update the entry field.
The general form is
#do stuff with the widgets and the application-specific functions
#do some other stuff
elif wid== another_button:
#or something else entirely
The Entry widget is a text field. You create them and place
them just like the other widgets. To retrieve the
information from the Entry, you can write
which returns a string. To write a string s in the Entry,
you can use
That is, you have to first delete the present contents of the
Entry, starting at position 0, and then insert the new contents
before position 0. This is a bit annoying, but the
documentation does not describe any methods for replacing the old
contents of an Entry in a single statement.
You may find that drawing in a canvas is not carried out when the
drawing statement ought to be executed. Writing
where win is the name assigned to the window, before the call to
the drawing function, fixes this. (The reason is something
like this: The statements in the GUI program are not executed in
lockstep, where one statement is completely executed before the
next one is processed, but instead in a more asynchronous fashion
where some tasks are postponed until others, invoked later, have
completed. So this statement causes postponed drawing
statements to complete execution. But honestly, it's a bit of a
mystery to me.)
You can also test this separately, to make sure it looks right.
Finally, we'll put the whole thing together by adding the glue of
the event handler. The complete program is shown
below. Note that we rely on particular methods of the Entry
widget to insert and delete text from the entry field.
#Jack and Jill
from Tkinter import *
choice = random.randint(0,1)
return "Help! I'm falling down!"
return "Oh no! I broke my crown!"
choice = random.randint(0,1)
return "Jack, wait for me!"
return "OMG, I'm tumbling!"
elif widg == jackbutton:
win = Tk()