Professional Documents
Culture Documents
Tkinter
Tkinter
Introduction to Tkinter
In this part of the Tkinter tutorial, we will introduce the Tkinter toolkit and create our
first programs.
The purpose of this tutorial is to get you started with the Tkinter toolkit. Images used
in this tutorial can be downloaded here. I used some icons from the Tango icons pack
of the Gnome project.
Tkinter
Tkinter is a Python binding to the Tk GUI toolkit. Tk is the original GUI library for the
Tcl language. Tkinter is implemented as a Python wrapper around a complete Tcl
interpreter embedded in the Python interpreter. There are several other popular
Python GUI toolkits. Most popular are wxPython, PyQt, and PyGTK.
Python
1 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
2.x versions. It will take some time till the software base and programmers will
migrate to Python 3.x. Today, Python is maintained by a large group of volunteers
worldwide. Python is open source software.
Python programming language supports several programming styles. It does not force
a programmer to a specific paradigm. Python supports object oriented and procedural
programming. There is also a limited support for functional programming.
The official web site for the Python programming language is python.org
Simple example
simple.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Simple")
self.pack(fill=BOTH, expand=1)
2 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
While this code is very small, the application window can do quite a lot. It can be
resized, maximized, or minimized. All the complexity that comes with it has been
hidden from the application programmer.
Here we import Tk and Frame classes. The first class is used to create a root window.
The latter is a container for other widgets.
class Example(Frame):
Our example class inherits from the Frame container widget. In the __init__()
constructor method we call the constructor of our inherited class. The background
self.parent = parent
We save a reference to the parent widget. The parent widget is the Tk root window in
our case.
self.initUI()
self.parent.title("Simple")
self.pack(fill=BOTH, expand=1)
3 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
The pack() method is one of the three geometry managers in Tkinter. It organizes
widgets into horizontal and vertical boxes. Here we put the Frame widget, accessed via
the self attribute to the Tk root window. It is expanded in both directions. In other
words, it takes the whole client space of the root window.
root = Tk()
The root window is created. The root window is a main application window in our
programs. It has a title bar and borders. These are provided by the window manager.
It must be created before any other widgets.
root.geometry("250x150+300+300")
The geometry() method sets a size for the window and positions it on the screen. The
first two parameters are the width and height of the window. The last two parameters
are x and y screen coordinates.
app = Example(root)
root.mainloop()
Finally, we enter the mainloop. The event handling starts from this point. The
mainloop receives events from the window system and dispatches them to the
application widgets. It is terminated when we click on the close button of the titlebar
or call the quit() method.
Centering window
4 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
center.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.parent.title("Centered window")
self.pack(fill=BOTH, expand=1)
self.centerWindow()
def centerWindow(self):
w = 290
h = 150
sw = self.parent.winfo_screenwidth()
sh = self.parent.winfo_screenheight()
x = (sw - w)/2
y = (sh - h)/2
self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y))
def main():
root = Tk()
ex = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
5 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
We need to have the size of the window and the size of the screen to position the
window in the center of the monitor screen.
w = 290
h = 150
These are the width and height values of the application window.
sw = self.parent.winfo_screenwidth()
sh = self.parent.winfo_screenheight()
x = (sw - w)/2
y = (sh - h)/2
Finally, the geometry() method is used to place the window in the center of the screen.
Quit button
In the last example of this section, we will create a quit button. When we press this
button, the application terminates.
quitbutton.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
6 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Quit button")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
We position a Button on the window. Clicking on the button will terminate the
application.
Tkinter supports theming of widgets. Widgets that are themed can be imported from
the ttk module. At the time of this writing, not all widgets are themable. For instance,
menus or listboxes are not supported so far.
self.style = Style()
self.style.theme_use("default")
We apply a theme for our widgets. Some of the supported themes are clam, default,
alt, or classic.
7 of 8 01/18/16 23:04
Introduction to Tkinter file:///home/odroid/Python/ZetCode/Introduction t...
We create an instance of the Button widget. The parent of this button is the Frame
container. We provide a label for the button and a command. The command specifies a
method that is called when we press the button. In our case the quit() method is
called, which terminates the application.
quitButton.place(x=50, y=50)
We use the place geometry manager to position the button in absolute coordinates
—50x50px from the top-left corner of the window.
8 of 8 01/18/16 23:04
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
When we design the GUI of our application, we decide what widgets we will use and
how we will organise those widgets in the application. To organise our widgets, we
use specialised non-visible objects called layout managers.
There are two kinds of widgets: containers and their children. The containers group
their children into suitable layouts.
Tkinter has three built-in layout managers: the pack, grid, and place managers. The place
geometry manager positions widgets using absolute positioning. The pack geometry
manager organises widgets in horizontal and vertical boxes. The grid geometry
manager places widgets in a two dimensional grid.
Absolute positioning
In most cases, programmers should use layout managers. There are a few situations
where we could use absolute positioning. In absolute positioning, the programmer
specifies the position and the size of each widget in pixels. The size and the position
of a widget do not change if we resize a window. Applications look different on various
platforms, and what looks OK on Linux, might not look OK on Mac OS. Changing fonts
in our application might spoil the layout. If we translate our application into another
language, we must redo our layout.
absolute.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
1 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Absolute positioning")
self.pack(fill=BOTH, expand=1)
Style().configure("TFrame", background="#333")
bard = Image.open("bardejov.jpg")
bardejov = ImageTk.PhotoImage(bard)
label1 = Label(self, image=bardejov)
label1.image = bardejov
label1.place(x=20, y=20)
rot = Image.open("rotunda.jpg")
rotunda = ImageTk.PhotoImage(rot)
label2 = Label(self, image=rotunda)
label2.image = rotunda
label2.place(x=40, y=160)
minc = Image.open("mincol.jpg")
mincol = ImageTk.PhotoImage(minc)
label3 = Label(self, image=mincol)
label3.image = mincol
label3.place(x=170, y=50)
def main():
root = Tk()
root.geometry("300x280+300+300")
app = Example(root)
root.mainloop()
2 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
if __name__ == '__main__':
main()
In this example, we place three images using absolute positioning. We use the place
geometry manager.
We use Image and ImageTk from the Python Imaging Library (PIL) module.
style = Style()
style.configure("TFrame", background="#333")
bard = Image.open("bardejov.jpg")
bardejov = ImageTk.PhotoImage(bard)
We create an image object and a photo image object from an image in the current
working directory.
label1.image = bardejov
We must keep the reference to the image to prevent image from being garbage
collected.
label1.place(x=20, y=20)
3 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
Buttons example
In the following example, we position two buttons in the bottom-right corner of the
window. We use the pack manager.
buttons.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
4 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
self.initUI()
def initUI(self):
self.parent.title("Buttons")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=True)
def main():
root = Tk()
root.geometry("300x200+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
We have two frames. There is the base frame and an additional frame, which expands
in both directions and push the two buttons to the bottom of the base frame. The
buttons are placed in a horizontal box and placed to the right of this box.
We create another Frame widget. This widget takes the bulk of the area. We change the
border of the frame so that the frame is visible; by default it is flat.
A closeButton is created. It is put into a horizontal box. The side parameter causes the
button to be placed to the right of the horizontal. The padx and the pady parameters put
some space between the widgets. The padx puts some space between the button
widgets and between the closeButton and the right border of the root window. The pady
5 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
puts some space between the button widgets and the borders of the frame and the
borders of the root window.
okButton.pack(side=RIGHT)
The okButton is placed next to the closeButton with 5 px space between them.
Review
The pack manager is a simple layout manager. It can be used to do simple layout tasks.
In order to create more complicated layouts, we need to utilise more frames, each
having its own pack manager.
review.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
6 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Review")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
entry1 = Entry(frame1)
entry1.pack(fill=X, padx=5, expand=True)
frame2 = Frame(self)
frame2.pack(fill=X)
entry2 = Entry(frame2)
entry2.pack(fill=X, padx=5, expand=True)
frame3 = Frame(self)
frame3.pack(fill=BOTH, expand=True)
txt = Text(frame3)
txt.pack(fill=BOTH, pady=5, padx=5, expand=True)
def main():
root = Tk()
root.geometry("300x300+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
The example shows how to create a more complex layout with multiple frames and
7 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
pack managers.
self.pack(fill=BOTH, expand=True)
The first frame is the base frame, on which other frames are placed. Note that in
addition to organising children within frames, we also manage the frames on the base
frame.
frame1 = Frame(self)
frame1.pack(fill=X)
entry1 = Entry(frame1)
entry1.pack(fill=X, padx=5, expand=True)
The first two widgets are placed on the first frame. The entry is horizontally streched
with the fill and the expand parameters.
frame3 = Frame(self)
frame3.pack(fill=BOTH, expand=True)
txt = Text(frame3)
txt.pack(fill=BOTH, pady=5, padx=5, expand=True)
Inside the third frame, we place a label and a text widget. The label is anchored to the
north. The text widget takes the whole remaining area.
8 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
Calculator
calculator.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
9 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
self.initUI()
def initUI(self):
self.parent.title("Calculator")
self.columnconfigure(0, pad=3)
self.columnconfigure(1, pad=3)
self.columnconfigure(2, pad=3)
self.columnconfigure(3, pad=3)
self.rowconfigure(0, pad=3)
self.rowconfigure(1, pad=3)
self.rowconfigure(2, pad=3)
self.rowconfigure(3, pad=3)
self.rowconfigure(4, pad=3)
entry = Entry(self)
entry.grid(row=0, columnspan=4, sticky=W+E)
cls = Button(self, text="Cls")
cls.grid(row=1, column=0)
bck = Button(self, text="Back")
bck.grid(row=1, column=1)
lbl = Button(self)
lbl.grid(row=1, column=2)
clo = Button(self, text="Close")
clo.grid(row=1, column=3)
sev = Button(self, text="7")
sev.grid(row=2, column=0)
eig = Button(self, text="8")
eig.grid(row=2, column=1)
nin = Button(self, text="9")
nin.grid(row=2, column=2)
div = Button(self, text="/")
div.grid(row=2, column=3)
10 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
self.pack()
def main():
root = Tk()
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
We configure the Button widget to have a specific font and to have some internal
padding.
self.columnconfigure(0, pad=3)
...
self.rowconfigure(0, pad=3)
We use the columnconfigure() and the rowconfigure() methods to define some space in grid
columns and rows. This way we achieve that the buttons are separated by some
space.
entry = Entry(self)
entry.grid(row=0, columnspan=4, sticky=W+E)
The Entry widget is where the digits are displayed. The widget is placed in the first
row and it spans all four columns. Widgets may not occupy all the space allotted by
11 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
cells in the grid. The sticky parameter expands the widget in a given direction. In our
case we ensure that the entry widget is expanded from left to right.
The cls button is placed in the second row and first column. Note that the rows and
columns start at zero.
self.pack()
The pack() method shows the frame widget and gives it initial size. If no other
parameters are given, the size will be just enough to show all children. This method
packs the frame widget to the toplevel root window, which is also a container. The grid
Figure: Calculator
Windows example
The following example creates the windows dialog using the grid geometry manager.
windows.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
12 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Windows")
self.pack(fill=BOTH, expand=True)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=4,
padx=5, sticky=E+W+S+N)
def main():
root = Tk()
root.geometry("350x300+300+300")
app = Example(root)
root.mainloop()
13 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
if __name__ == '__main__':
main()
In this example, we use a Label widget, a Text widget, and four buttons.
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
We define some space among widgets in the grid. The weight parameter makes the
second column and fourth row growable. This row and column is occupied by the text
widget, so all the extra space is taken by it.
The label widget is created and put into the grid. If no column and row is specified,
then the first column or row is assumed. The label sticks to the west and it has some
padding around its borders.
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=4,
padx=5, sticky=E+W+S+N)
The text widget is created and starts from the second row and first column. It spans
two columns and four rows. There is a 4 px space between the widget and the left
border of the root window. Finally, the widget sticks to all the four sides. So when the
window is resized, the text widget grows in all directions.
14 of 15 01/18/16 23:07
Layout management in Tkinter file:///home/odroid/Python/ZetCode/Layout mana...
These two buttons go below the text widget; the Help button takes the first column,
the Ok Button takes the last column.
15 of 15 01/18/16 23:07
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
Tkinter widgets
In this part of the Tkinter tutorial, we will cover some basic Tkinter widgets. We work
with the following widgets: Checkbutton, Label, Scale, and Listbox.
Widgets are basic building blocks of a GUI application. Over the years, several
widgets became a standard in all toolkits on all OS platforms; for example a button, a
check box or a scroll bar. Some of them might have different names. For instance, a
check box is called a check button in Tkinter. Tkinter has a small set of widgets which
cover basic programming needs. More specialised widgets can be created as custom
widgets.
Checkbutton
Checkbutton is a widget that has two states: on and off. The on state is visualized by a
check mark. (Some themes may have different visuals.) It is used to denote some
boolean property. The Checkbutton widget provides a check box with a text label.
checkbutton.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
1 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Checkbutton")
self.pack(fill=BOTH, expand=True)
self.var = BooleanVar()
def onClick(self):
if self.var.get() == True:
self.master.title("Checkbutton")
else:
self.master.title("")
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
In our example, we place a check button on the window. The check button shows or
hides the title of the window.
self.var = BooleanVar()
We create an BooleanVar object. It is a value holder for Boolean values for widgets in
Tkinter.
2 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
An instance of the Checkbutton is created. The value holder is connected to the widget
via the variable parameter. When we click on the check button, the onClick() method is
called. This is done with the command parameter.
cb.select()
Initially, the title is shown in the titlebar. So at the start, we make it checked with the
select() method.
if self.var.get() == True:
self.master.title("Checkbutton")
else:
self.master.title("")
Inside the onClick() method, we display or hide the title based on the value from the
self.var variable.
Figure: Checkbutton
Label
The Label widget is used to display text or images. No user interaction is available.
label.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
3 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Label")
self.img = Image.open("tatras.jpg")
tatras = ImageTk.PhotoImage(self.img)
label = Label(self, image=tatras)
label.pack()
self.pack()
def setGeometry(self):
w, h = self.img.size
self.parent.geometry(("%dx%d+300+300") % (w, h))
def main():
root = Tk()
ex = Example(root)
ex.setGeometry()
root.mainloop()
4 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
if __name__ == '__main__':
main()
By default, the Label widget can display only a limited set of image types. To display a
JPG image, we must use the PIL, Python Imaging Library module.
self.img = Image.open("tatras.jpg")
tatras = ImageTk.PhotoImage(self.img)
We create an image from the image file in the current working directory. Later we
create a photo image from the image.
label.image = tatras
w, h = self.img.size
self.parent.geometry(("%dx%d+300+300") % (w, h))
Scale
Scale is a widget that lets the user graphically select a value by sliding a knob within a
bounded interval. Our example will show a selected number in a label widget.
scale.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
5 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Scale")
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
self.var = IntVar()
self.label = Label(self, text=0, textvariable=self.var)
self.label.pack(side=LEFT)
v = int(float(val))
self.var.set(v)
def main():
root = Tk()
ex = Example(root)
root.geometry("250x100+300+300")
root.mainloop()
if __name__ == '__main__':
main()
We have two widgets in the above script: a scale and a label. A value from the scale
6 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
A Scale widget is created. We provide the lower and upper bounds. The from is a
regular Python keyword that is why there is an underscore after the first parameter.
When we move the knob of the scale, the onScale() method is called.
self.var = IntVar()
self.label = Label(self, text=0, textvariable=self.var)
An integer value holder and label widget are created. Value from the holder is shown
in the label widget.
v = int(float(val))
self.var.set(v)
The onScale() method receives a currently selected value from the scale widget as a
parameter. The value is first converted to a float and then to integer. Finally, the value
is set to the value holder of the label widget.
Figure: Scale
Listbox
Listbox is a widget that displays a list of objects. It allows the user to select one or
more items.
listbox.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
7 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Listbox")
self.pack(fill=BOTH, expand=1)
lb = Listbox(self)
for i in acts:
lb.insert(END, i)
lb.bind("<<ListboxSelect>>", self.onSelect)
lb.pack(pady=15)
self.var = StringVar()
self.label = Label(self, text=0, textvariable=self.var)
self.label.pack()
sender = val.widget
idx = sender.curselection()
value = sender.get(idx)
self.var.set(value)
8 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
In our example, we show a list of actresses in the Listbox. The currently selected
actress is displayed in a label widget.
lb = Listbox(self)
for i in acts:
lb.insert(END, i)
We create an instance of the Listbox and insert all the items from the above mentioned
list.
lb.bind("<<ListboxSelect>>", self.onSelect)
When we select an item in the listbox, the <<ListboxSelect>> event is generated. We bind
the onSelect() method to this event.
self.var = StringVar()
self.label = Label(self, text=0, textvariable=self.var)
A label and its value holder is created. In this label we will display the currently
selected item.
sender = val.widget
idx = sender.curselection()
We find out the index of the selected item using the curselection() method.
value = sender.get(idx)
9 of 10 01/18/16 23:08
Tkinter widgets http://zetcode.com/gui/tkinter/widgets/
The actual value is retrieved with the get() method, which takes the index of the item.
self.var.set(value)
In this part of the Tkinter tutorial, we have presented several Tkinter widgets.
10 of 10 01/18/16 23:08
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
A menubar is one of the most visible parts of the GUI application. It is a group of
commands located in various menus. While in console applications we must
remember many arcane commands, here we have most of the commands grouped into
logical parts. There are accepted standards that further reduce the amount of time
spending to learn a new application. Menus group commands that we can use in an
application. Toolbars provide a quick access to the most frequently used commands.
Simple menu
simplemenu.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
1 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Simple menu")
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Exit", command=self.onExit)
menubar.add_cascade(label="File", menu=fileMenu)
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Our example will show a menu with one item. By selecting the exit menu item we
close the application.
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Exit", command=self.onExit)
2 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
We add a command to the file menu. The command will call the onExit() method.
menubar.add_cascade(label="File", menu=fileMenu)
The file menu is added to the menubar using the add_cascade() method.
Submenu
A submenu is a menu plugged into another menu object. The next example
demonstrates this.
submenu.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
3 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
self.initUI()
def initUI(self):
self.parent.title("Submenu")
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
submenu = Menu(fileMenu)
submenu.add_command(label="New feed")
submenu.add_command(label="Bookmarks")
submenu.add_command(label="Mail")
fileMenu.add_cascade(label='Import', menu=submenu, underline=0)
fileMenu.add_separator()
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
submenu = Menu(fileMenu)
submenu.add_command(label="New feed")
submenu.add_command(label="Bookmarks")
submenu.add_command(label="Mail")
4 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
By adding the menu to the fileMenu and not to the menubar, we create a submenu. The
underline parameter creates a keyboard shortcut. It provides the character position
which should be underlined. In our case it is the first. Positions start from zero. When
we click on the File menu, a popup window is shown. The Import menu has one
character underlined. We can select it either with the mouse pointer or with the Alt+I
shortcut.
fileMenu.add_separator()
A separator is a horizontal line that visually separates menu commands. This way we
can group items into some logical places.
Figure: Submenu
Popup menu
In the next example, we create a popup menu. Popup menu is also called a context
menu. It can be shown anywhere on the client area of a window.
popupmenu.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
5 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Popup menu")
self.menu = Menu(self.parent, tearoff=0)
self.menu.add_command(label="Beep", command=self.bell())
self.menu.add_command(label="Exit", command=self.onExit)
self.parent.bind("<Button-3>", self.showMenu)
self.pack()
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
A context menu is a regular Menu widget. The tearoff feature is turned off. Now it is not
possible to separate the menu into a new toplevel window.
self.parent.bind("<Button-3>", self.showMenu)
6 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
We bind the <Button-3> event to the showMenu() method. The event is generated when we
right click on the client area of the window.
The showMenu() method shows the context menu. The popup menu is shown at the x and
y coordinates of the mouse click.
Toolbar
Menus group commands that we can use in an application. Toolbars provide a quick
access to the most frequently used commands. There is no toolbar widget in Tkinter.
toolbar.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
7 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Toolbar")
menubar = Menu(self.parent)
self.fileMenu = Menu(self.parent, tearoff=0)
self.fileMenu.add_command(label="Exit", command=self.onExit)
menubar.add_cascade(label="File", menu=self.fileMenu)
self.img = Image.open("exit.png")
eimg = ImageTk.PhotoImage(self.img)
toolbar.pack(side=TOP, fill=X)
self.parent.config(menu=menubar)
self.pack()
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("250x150+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
8 of 9 01/18/16 23:09
Menus & toolbars in Tkinter http://zetcode.com/gui/tkinter/menustoolbars/
self.img = Image.open("exit.png")
eimg = ImageTk.PhotoImage(self.img)
Image and a photo image for the toolbar button are created.
The toolbar is a frame and a frame is a container widget. We pack the button to the
left side. We add some padding.
toolbar.pack(side=TOP, fill=X)
The toolbar itself is packed to the top of the toplevel window; it is horizontally
stretched.
Figure: Toolbar
In this part of the Tkinter tutorial, we worked with menus and toolbars.
9 of 9 01/18/16 23:09
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
Dialogs in Tkinter
In this part of the Tkinter tutorial, we will work with dialogs.
Message boxes
Message boxes are convenient dialogs that provide messages to the user of the
application. The message consists of text and image data. Message boxes in Tkinter
are located in the tkMessageBox module.
messagebox.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
1 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Message boxes")
self.pack()
def onError(self):
mbox.showerror("Error", "Could not open file")
def onWarn(self):
mbox.showwarning("Warning", "Deprecated function call")
def onQuest(self):
mbox.askquestion("Question", "Are you sure to quit?")
def onInfo(self):
mbox.showinfo("Information", "Download completed")
def main():
root = Tk()
ex = Example(root)
root.geometry("300x150+300+300")
root.mainloop()
if __name__ == '__main__':
main()
We use the grid manager to set up a grid of four buttons. Each of the buttons shows a
different message box.
2 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
We import the tkMessageBox which has the functions that show dialogs.
We create an error button, which calls the onError() method. Inside the method, we
show the error message dialog.
def onError(self):
box.showerror("Error", "Could not open file")
In case we pressed the error button, we show the error dialog. We use the showerror()
function to show the dialog on the screen. The first parameter of this method is the
title of the message box, the second parameter is the actual message.
Color chooser
The color chooser is a dialog for selecting a colour. It is located in the tkColorChooser
module.
colorchooser.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
3 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Color chooser")
self.pack(fill=BOTH, expand=1)
def onChoose(self):
def main():
root = Tk()
ex = Example(root)
root.geometry("300x150+300+300")
root.mainloop()
if __name__ == '__main__':
main()
We have a button and a frame. Clicking on the button we show a color chooser dialog.
We will change the background color of the frame by selecting a colour from the
dialog.
The askcolor() function shows the dialog. If we click OK, a tuple is returned. It is a
colour value in RGB and hexadecimal format. In the second line we change the
background colour of the frame with the returned colour value.
4 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
Figure: tkColorChooser
File dialog
filedialog.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("File dialog")
5 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Open", command=self.onOpen)
menubar.add_cascade(label="File", menu=fileMenu)
self.txt = Text(self)
self.txt.pack(fill=BOTH, expand=1)
def onOpen(self):
if fl != '':
text = self.readFile(fl)
self.txt.insert(END, text)
f = open(filename, "r")
text = f.read()
return text
def main():
root = Tk()
ex = Example(root)
root.geometry("300x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
In our code example, we use the tkFileDialog dialog to select a file and display its
contents in a Text widget.
self.txt = Text(self)
This is the Text widget in which we will show the contents of a selected file.
6 of 7 01/18/16 23:10
Dialogs in Tkinter http://zetcode.com/gui/tkinter/dialogs/
These are file filters. The first shows only Python files, the other shows all files.
The dialog is created and shown on the screen. We get the return value, which is the
name of the selected file.
text = self.readFile(fl)
self.txt.insert(END, text)
Figure: tkFileDialog
7 of 7 01/18/16 23:10
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
Drawing in Tkinter
In this part of the Tkinter tutorial we will do some drawing. Drawing in Tkinter is
done on the Canvas widget. Canvas is a high-level facility for doing graphics in Tkinter.
Lines
A line is a simple geometric primitive. The create_line() method creates a line item on
the Canvas.
lines.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
1 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
def initUI(self):
self.parent.title("Lines")
self.pack(fill=BOTH, expand=1)
canvas = Canvas(self)
canvas.create_line(15, 25, 200, 25)
canvas.create_line(300, 35, 300, 200, dash=(4, 2))
canvas.create_line(55, 85, 155, 85, 105, 180, 55, 85)
canvas.pack(fill=BOTH, expand=1)
def main():
root = Tk()
ex = Example(root)
root.geometry("400x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
The parameters of the create_line() method are the x and y coordinates of the start and
end points of the line.
A vertical line is drawn. The dash option specifies the dash pattern of the line. We have
a line consisting of alternating segments of 4 px dash and 2 px space.
The create_line() method can take multiple points. This line draws a triangle.
2 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
Figure: Lines
Colours
colours.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
3 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
def initUI(self):
self.parent.title("Colours")
self.pack(fill=BOTH, expand=1)
canvas = Canvas(self)
canvas.create_rectangle(30, 10, 120, 80,
outline="#fb0", fill="#fb0")
canvas.create_rectangle(150, 10, 240, 80,
outline="#f50", fill="#f50")
canvas.create_rectangle(270, 10, 370, 80,
outline="#05f", fill="#05f")
canvas.pack(fill=BOTH, expand=1)
def main():
root = Tk()
ex = Example(root)
root.geometry("400x100+300+300")
root.mainloop()
if __name__ == '__main__':
main()
In the code example, we draw three rectangles and fill them with different colour
values.
canvas = Canvas(self)
The create_rectangle() creates a rectangle item on the canvas. The first four parameters
are the x and y coordinates of the two bounding points: the top-left and bottom-right
points. With the outline parameter we control the colour of the outline of the
rectangle. Likewise, the fill parameter provides a colour for the inside of the
rectangle.
4 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
Figure: Colours
Shapes
We can draw various shapes on the Canvas. The following code example will show some
of them.
shapes.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Shapes")
self.pack(fill=BOTH, expand=1)
canvas = Canvas(self)
canvas.create_oval(10, 10, 80, 80, outline="gray",
fill="gray", width=2)
canvas.create_oval(110, 10, 210, 80, outline="gray",
5 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
fill="gray", width=2)
canvas.create_rectangle(230, 10, 290, 60,
outline="gray", fill="gray", width=2)
canvas.create_arc(30, 200, 90, 100, start=0,
extent=210, outline="gray", fill="gray", width=2)
canvas.pack(fill=BOTH, expand=1)
def main():
root = Tk()
ex = Example(root)
root.geometry("330x220+300+300")
root.mainloop()
if __name__ == '__main__':
main()
We draw five different shapes on the window: a circle, an ellipse, a rectangle, an arc,
and a polygon. Outlines are drawn in red and insides in green. The width of the
outline is 2 px.
Here the create_oval() method is used to create a circle item. The first four parameters
are the bounding box coordinates of the circle. In other words, they are x and y
coordinates of the top-left and bottom-right points of the box, in which the circle is
drawn.
We create a rectangle item. The coordinates are again the bounding box of the
rectangle to be drawn.
This code line creates an arc. An arc is a part of the circumference of the circle. We
provide the bounding box. The start parameter is the start angle of the arc. The extent
6 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
Figure: Shapes
Drawing image
draw_image.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
7 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("High Tatras")
self.pack(fill=BOTH, expand=1)
self.img = Image.open("tatras.jpg")
self.tatras = ImageTk.PhotoImage(self.img)
def main():
root = Tk()
ex = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
self.img = Image.open("tatras.jpg")
self.tatras = ImageTk.PhotoImage(self.img)
Tkinter does not support JPG images internally. As a workaround, we use the Image and
ImageTk modules.
We create the Canvas widget. It takes the size of the image into account. It is 20 px
wider and 20 px higher than the actual image size.
8 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
We use the create_image() method to create an image item on the canvas. To show the
whole image, it is anchored to the north and to the west. The image parameter provides
the photo image to display.
Drawing text
draw_text.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
class Example(Frame):
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Lyrics")
self.pack(fill=BOTH, expand=1)
canvas = Canvas(self)
canvas.create_text(20, 30, anchor=W, font="Purisa",
text="Most relationships seem so transitory")
canvas.create_text(20, 60, anchor=W, font="Purisa",
text="They're good but not the permanent one")
canvas.create_text(20, 130, anchor=W, font="Purisa",
text="Who doesn't long for someone to hold")
canvas.create_text(20, 160, anchor=W, font="Purisa",
text="Who knows how to love without being told")
9 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
def main():
root = Tk()
ex = Example(root)
root.geometry("420x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
The first two parameters are the x and y coordinates of the center point of the text. If
we anchor the text item to the west, the text starts from this position. The font
parameter provides the font of the text and the text parameter is the text to be
displayed.
10 of 11 01/18/16 23:11
Drawing in Tkinter http://zetcode.com/gui/tkinter/drawing/
11 of 11 01/18/16 23:11
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
Nibbles in Tkinter
In this part of the Tkinter tutorial, we create a Nibbles game clone.
Nibbles is an older classic video game. It was first created in late 70s. Later it was
brought to PCs. In this game the player controls a snake. The objective is to eat as
many apples as possible. Each time the snake eats an apple, its body grows. The
snake must avoid the walls and its own body.
Development
The size of each of the joints of a snake is 10 px. The snake is controlled with the
cursor keys. Initially, the snake has three joints. The game starts immediately. When
the game is finished, we display "Game Over" message in the center of the window.
We use the Canvas widget to create the game. The objects in the game are images. We
use canvas methods to create image items. We use canvas methods to find items on
the canvas using tags and to do collision detection.
nibbles.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode Tkinter tutorial
import sys
1 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
import random
from PIL import Image, ImageTk
from Tkinter import Tk, Frame, Canvas, ALL, NW
WIDTH = 300
HEIGHT = 300
DELAY = 100
DOT_SIZE = 10
ALL_DOTS = WIDTH * HEIGHT / (DOT_SIZE * DOT_SIZE)
RAND_POS = 27
x = [0] * ALL_DOTS
y = [0] * ALL_DOTS
class Board(Canvas):
self.parent = parent
self.initGame()
self.pack()
def initGame(self):
self.left = False
self.right = True
self.up = False
self.down = False
self.inGame = True
self.dots = 3
self.apple_x = 100
self.apple_y = 190
for i in range(self.dots):
x[i] = 50 - i * 10
y[i] = 50
try:
self.idot = Image.open("dot.png")
self.dot = ImageTk.PhotoImage(self.idot)
self.ihead = Image.open("head.png")
self.head = ImageTk.PhotoImage(self.ihead)
self.iapple = Image.open("apple.png")
self.apple = ImageTk.PhotoImage(self.iapple)
except IOError, e:
print e
2 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
sys.exit(1)
self.focus_get()
self.createObjects()
self.locateApple()
self.bind_all("<Key>", self.onKeyPressed)
self.after(DELAY, self.onTimer)
def createObjects(self):
def checkApple(self):
apple = self.find_withtag("apple")
head = self.find_withtag("head")
if apple[0] == ovr:
x, y = self.coords(apple)
self.create_image(x, y, image=self.dot, anchor=NW, tag="dot")
self.locateApple()
def doMove(self):
dots = self.find_withtag("dot")
head = self.find_withtag("head")
z = 0
while z < len(items)-1:
c1 = self.coords(items[z])
c2 = self.coords(items[z+1])
self.move(items[z], c2[0]-c1[0], c2[1]-c1[1])
z += 1
if self.left:
self.move(head, -DOT_SIZE, 0)
3 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
if self.right:
self.move(head, DOT_SIZE, 0)
if self.up:
self.move(head, 0, -DOT_SIZE)
if self.down:
self.move(head, 0, DOT_SIZE)
def checkCollisions(self):
dots = self.find_withtag("dot")
head = self.find_withtag("head")
if x1 < 0:
self.inGame = False
if y1 < 0:
self.inGame = False
def locateApple(self):
apple = self.find_withtag("apple")
self.delete(apple[0])
r = random.randint(0, RAND_POS)
self.apple_x = r * DOT_SIZE
r = random.randint(0, RAND_POS)
self.apple_y = r * DOT_SIZE
key = e.keysym
4 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
def onTimer(self):
if self.inGame:
self.checkCollisions()
self.checkApple()
self.doMove()
self.after(DELAY, self.onTimer)
else:
self.gameOver()
def gameOver(self):
self.delete(ALL)
self.create_text(self.winfo_width()/2, self.winfo_height()/2,
text="Game Over", fill="white")
class Nibbles(Frame):
parent.title('Nibbles')
self.board = Board(parent)
self.pack()
5 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
def main():
root = Tk()
nib = Nibbles(root)
root.mainloop()
if __name__ == '__main__':
main()
The WIDTH and HEIGHT constants determine the size of the Board. The DELAY constant
determines the speed of the game. The DOT_SIZE is the size of the apple and the dot of
the snake. The ALL_DOTS constant defines the maximum number of possible dots on the
Board. The RAND_POS constant is used to calculate a random position of an apple.
x = [0] * ALL_DOTS
y = [0] * ALL_DOTS
These two arrays store the x and y coordinates of all possible joints of a snake.
The initGame() method initialises variables, loads images, and starts a timeout function.
try:
self.idot = Image.open("dot.png")
self.dot = ImageTk.PhotoImage(self.idot)
self.ihead = Image.open("head.png")
self.head = ImageTk.PhotoImage(self.ihead)
self.iapple = Image.open("apple.png")
self.apple = ImageTk.PhotoImage(self.iapple)
except IOError, e:
print e
sys.exit(1)
In these lines, we load our images. There are three images in the Nibbles game: the
head, the dot, and the apple.
self.createObjects()
self.locateApple()
The createObjects() method creates items on the canvas. The locateApple() puts an apple
randomly on the canvas.
self.bind_all("<Key>", self.onKeyPressed)
6 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
We bind the keyboard events to the onKeyPressed() method. The game is controlled with
keyboard cursor keys.
def createObjects(self):
In the createObjects() method, we create game objects on the canvas. These are canvas
items. They are given initial x and y coordinates. The image parameter provides the
image to be displayed. The anchor parameter is set to NW; this way the coordinates of
the canvas item are the top-left points of the items. This is important if we want to be
able to display images next to the borders of the root window. Try to delete the anchor
and see what happens. The tag parameter is used to identify items on the canvas. One
tag may be used for multiple canvas items.
The checkApple() method checks if the snake has hit the apple object. If so, we add
another snake joint and call the locateApple().
apple = self.find_withtag("apple")
head = self.find_withtag("head")
The find_withtag() method finds an item on the canvas using its tag. We need two
items: the head of the snake and the apple. Note that even if there is only one item
with a given tag, the method returns a tuple. This is a case for the apple item. And
later the apple item is accessed the following way: apple[0].
The bbox() method returns the bounding box points of an item. The find_overlapping()
if apple[0] == ovr:
x, y = self.coords(apple)
self.create_image(x, y, image=self.dot, anchor=NW, tag="dot")
self.locateApple()
If the apple collides with the head, we create a new dot item at the coordinates of the
7 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
apple object. We call the locateApple() method, which deletes the old apple item from
the canvas and creates and randomly positions a new one.
In the doMove() method we have the key algorithm of the game. To understand it, look
at how the snake is moving. We control the head of the snake. We can change its
direction with the cursor keys. The rest of the joints move one position up the chain.
The second joint moves where the first was, the third joint where the second was etc.
z = 0
while z < len(items)-1:
c1 = self.coords(items[z])
c2 = self.coords(items[z+1])
self.move(items[z], c2[0]-c1[0], c2[1]-c1[1])
z += 1
if self.left:
self.move(head, -DOT_SIZE, 0)
In the checkCollisions() method, we determine if the snake has hit itself or one of the
walls.
We finish the game if the snake hits one of its joints with the head.
We finish the game if the snake hits the bottom of the Board.
The locateApple() method locates a new apple randomly on the board and deletes the
old one.
apple = self.find_withtag("apple")
self.delete(apple[0])
8 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
Here we find and delete the apple that was eaten by the snake.
r = random.randint(0, RAND_POS)
self.apple_x = r * DOT_SIZE
...
self.apple_y = r * DOT_SIZE
In the onKeyPressed() method of the Board class, we determine the keys that were
pressed.
If we hit the left cursor key, we set left variable to true. This variable is used in the
doMove() method to change coordinates of the snake object. Notice also that when the
snake is heading to the right, we cannot turn immediately to the left.
def onTimer(self):
if self.inGame:
self.checkCollisions()
self.checkApple()
self.doMove()
self.after(DELAY, self.onTimer)
else:
self.gameOver()
Every DELAY ms, the onTimer() method is called. If we are in the game, we call three
methods that build the logic of the game. Otherwise the game is finished. The timer is
based on the after() method, which calls a method after DELAY ms only once. To
repeatedly call the timer, we recursively call the onTimer() method.
def gameOver(self):
self.delete(ALL)
self.create_text(self.winfo_width()/2, self.winfo_height()/2,
text="Game Over", fill="white")
9 of 10 01/18/16 23:12
Nibbles in Tkinter http://zetcode.com/gui/tkinter/nibbles/
If the game is over, we delete all items on the canvas. Then we draw "Game Over" in
the center of the screen.
Figure: Nibbles
This was the Nibbles computer game created with the Tkinter library.
10 of 10 01/18/16 23:12