Skip to content

Advanced Turtle and Event-Driven Programming

By the end of this lesson you'll be able to:

  • Explain the event-driven programming model and how it differs from sequential programs
  • Use turtle.onscreenclick() to respond to mouse clicks
  • Use turtle.onkey() and turtle.listen() to respond to keyboard presses
  • Use turtle.ontimer() to create repeating animation loops
  • Build a small interactive drawing program using events

Every game, app, and website uses event-driven programming — code that waits for something to happen (a click, a keypress, a timer) and then responds. This chapter teaches you how to build programs that react in real time.

Welcome to Chapter 35!

Monty waving welcome This is where your programs start feeling alive — responding to your mouse and keyboard in real time! Event-driven programming is the foundation of every game and interactive app. Let's make things move! Let's code it together!

The Event-Driven Model

In sequential programs, code runs top to bottom — each line executes after the previous one finishes.

In event-driven programs, the program starts an event loop that waits and watches. When an event occurs (mouse click, key press, timer tick), the loop calls a callback function you registered for that event.

1
2
3
4
5
6
7
[Register callbacks]  →  [Start event loop]  →  [Wait]
                                                  ↓
                                           [Event occurs]
                                                  ↓
                                       [Call the callback]
                                                  ↓
                                               [Wait]

You don't control when events fire — you just write the functions that handle them.

Three Key Concepts

Before we write interactive turtle code, here are three terms you'll see throughout this chapter:

  • Event — something that happens: a mouse click, key press, or timer expiring
  • Callback — the function you write to handle the event; you pass it as an argument
  • Event loop — the ongoing loop inside turtle.mainloop() that watches for events and calls callbacks

Mouse Click Events with onscreenclick()

turtle.onscreenclick(callback) registers a function to be called every time the user clicks on the turtle canvas.

The callback receives the x and y coordinates of the click as arguments.

What Do You Think Will Happen?

Monty thinking The code below draws a dot wherever the user clicks. But before you run it — how does the program know where the click happened? Think about how the callback receives the coordinates, then run it to see!


  

t.dot(size, color) draws a filled circle of the given diameter at the turtle's current position. Click anywhere on the canvas — a dot appears at each click location!

Keyboard Events with onkey() and listen()

screen.onkey(callback, key) registers a callback for a specific key. screen.listen() tells the screen to start paying attention to keyboard events — you must call this before keyboard events will work.

Key name strings include "Up", "Down", "Left", "Right", "space", "Return", and single letters like "a".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import turtle

screen = turtle.Screen()
t = turtle.Turtle()

def go_forward():
    t.forward(20)

def turn_left():
    t.left(15)

def turn_right():
    t.right(15)

screen.onkey(go_forward, "Up")
screen.onkey(turn_left,  "Left")
screen.onkey(turn_right, "Right")
screen.listen()   # must call listen() to activate keyboard events
screen.mainloop()

  

Use the arrow keys to steer the turtle around the canvas!

Timer Events with ontimer()

screen.ontimer(callback, delay_ms) calls callback once after delay_ms milliseconds.

The key technique for animation loops is re-registering the timer inside the callback — so it fires again and again:

1
2
3
4
5
6
7
def animate():
    t.forward(5)
    t.left(3)
    screen.ontimer(animate, 50)   # schedule ourselves again in 50ms

animate()   # start the loop
screen.mainloop()

This creates a smooth animation running at about 20 frames per second (1000 ÷ 50ms = 20 fps).


  

Combining Events — Interactive Art

The real power of event-driven programming emerges when you combine multiple event types. The example below lets you draw with the mouse and clear with the spacebar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import turtle

screen = turtle.Screen()
t = turtle.Turtle()
t.speed(0)
t.pensize(3)
t.pencolor("steelblue")

drawing = False

def start_draw(x, y):
    global drawing
    drawing = True
    t.penup()
    t.goto(x, y)
    t.pendown()

def draw(x, y):
    if drawing:
        t.goto(x, y)

def stop_draw(x, y):
    global drawing
    drawing = False

def clear_screen():
    t.clear()

screen.onscreenclick(start_draw, 1)   # left mouse button down
screen.onscreenclick(stop_draw,  3)   # right mouse button up
screen.onkey(clear_screen, "space")
screen.listen()
screen.mainloop()

The Event-Driven vs Sequential Comparison

Feature Sequential Event-Driven
Execution flow Top to bottom, predictable Waits for events, unpredictable order
User interaction Limited (input() only) Real-time (mouse, keyboard, timer)
Typical use Scripts, calculations Games, GUIs, apps
Complexity Low Medium — requires callback thinking

Callbacks Are Just Functions

Monty with a tip The hardest part of event-driven programming is trusting the callback pattern. You write the function. You register it. The system calls it when the event fires. You don't call it yourself — that's the event loop's job. Think of it like setting a phone alarm: you set it once, then it rings when the time comes.

Learning Check

Your Turn — Add a Color Changer

Monty thinking The code below draws dots on click, but all dots are the same color. Add a key event so pressing "c" cycles through a list of colors with each press!


  

Experiments

Try these changes. Predict what will happen first, then run it to check!

  1. Change the timer delay in the spiral lab from 20 to 5. Does the animation get faster or slower? You'll know it worked when you see the spiral build at a noticeably different speed.

  2. Add an "r" key binding that calls t.color("red") — pressing R changes the turtle's draw color to red. You'll know it worked when pressing R switches the draw color.

  3. Register a click callback that uses t.write() to stamp the click coordinates at each click location. You'll know it worked when "(x, y)" labels appear at every click spot.

  4. Modify the spiral to stop after 300 steps (instead of 200) and add a reset function on "s" that clears and restarts from step 0. You'll know it worked when pressing s clears and restarts the spiral.

  5. Create a "bouncing ball" — a circle that moves diagonally using a timer and reverses direction when it hits the canvas edges. You'll know it worked when the ball bounces around the canvas indefinitely.

Event-Driven Programmer!

Monty celebrating You've built programs that respond to the real world — clicks, key presses, and timed animations! Event-driven programming is the foundation of every game, app, and website UI. Two chapters to go — and they take you into the exciting world of AI and machine learning! Let's keep coding!

Take the Chapter Review Quiz

See Annotated References