Students build a working button from scratch (a rectangle, a label and a check that a click landed inside), and find out what every app's buttons are really doing.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min · Panel and toolkit 5 min
Turtle has no buttons, which is the point: students build one. The key idea is the hit test: a click at (x, y) is inside the button when x is between the left and right edges and y is between the bottom and top edges. Four comparisons joined with and. Run the counter and click inside and outside the button.
The hit test: four comparisons joined with and. Have them work out each comparison for one click on paper before fixing the code.
| What you will see | A question to ask | The fix |
|---|---|---|
| Clicks far from the button still count. | Are the four comparisons joined with and, or with or? | Use and. A click is inside only when all four comparisons are true. |
| Clicks inside the button are missed near the top or right. | What are the right and top edges, using bx, bw, by and bh? | The right edge is bx + bw and the top edge is by + bh. |
| The number on screen does not change, or numbers pile up on top of each other. | Does the click redraw the screen, and does the redraw clear the old drawing first? | Call draw_scene() after changing the count, and start draw_scene with clear(). |
One possible solution for each task. Other correct programs are fine.
from turtle import *
speed(0)
hideturtle()
bx = -100
by = -80
bw = 200
bh = 70
count = 0
def draw_scene():
clear()
penup()
goto(bx, by)
pendown()
for i in range(2):
forward(bw)
left(90)
forward(bh)
left(90)
penup()
goto(bx + 10, by + 25)
write("Click me")
goto(-20, 70)
write(count, False, "left", ("Arial", 24, "normal"))
def clicked(x, y):
global count
if x > bx and x < bx + bw and y > by and y < by + bh:
count = count + 1
draw_scene()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
from turtle import *
speed(0)
hideturtle()
bx = -60
by = -25
bw = 120
bh = 50
count = 0
def draw_scene():
clear()
penup()
goto(bx, by)
pendown()
for i in range(2):
forward(bw)
left(90)
forward(bh)
left(90)
penup()
goto(bx + 10, by + 15)
write("Click me")
goto(-20, 70)
write(count, False, "left", ("Arial", 24, "normal"))
def clicked(x, y):
global count
if x > bx and x < bx + bw and y > by and y < by + bh:
count = count + 5
draw_scene()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
from turtle import *
speed(0)
hideturtle()
count = 0
def draw_button(bx, by, label):
penup()
goto(bx, by)
pendown()
for i in range(2):
forward(100)
left(90)
forward(50)
left(90)
penup()
goto(bx + 40, by + 18)
write(label)
def draw_scene():
clear()
draw_button(-120, -25, "+1")
draw_button(20, -25, "-1")
goto(-10, 70)
write(count, False, "left", ("Arial", 24, "normal"))
def clicked(x, y):
global count
if x > -120 and x < -20 and y > -25 and y < 25:
count = count + 1
if x > 20 and x < 120 and y > -25 and y < 25:
count = count - 1
draw_scene()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
from turtle import *
speed(0)
hideturtle()
names = ["white", "yellow", "lightblue", "pink", "lightgreen"]
# Where each button goes: three on the top row, two below.
bxs = [-170, -60, 50, -170, -60]
bys = [20, 20, 20, -40, -40]
bw = 100
bh = 40
def draw_button(bx, by, label):
penup()
goto(bx, by)
pendown()
for i in range(2):
forward(bw)
left(90)
forward(bh)
left(90)
penup()
goto(bx + 10, by + 12)
write(label)
def clicked(x, y):
for i in range(len(names)):
if x > bxs[i] and x < bxs[i] + bw and y > bys[i] and y < bys[i] + bh:
bgcolor(names[i])
for i in range(len(names)):
draw_button(bxs[i], bys[i], names[i])
onscreenclick(clicked)
listen()
mainloop()
from turtle import *
from ui import draw_button, inside
speed(0)
hideturtle()
count = 0
draw_button(-140, -25, 120, 50, "Add one")
draw_button(20, -25, 120, 50, "Take one")
def clicked(x, y):
global count
if inside(x, y, -140, -25, 120, 50):
count = count + 1
print(count)
if inside(x, y, 20, -25, 120, 50):
count = count - 1
print(count)
onscreenclick(clicked)
listen()
mainloop()
Stretch: Add a third button that resets the count to 0, and draw the count in red when it goes below zero.
Support: Give students a printed grid with the button drawn and five click points marked, to decide inside or outside before coding.
A button has bx = 0, by = 0, bw = 100, bh = 40. Is a click at (50, 50) inside? Why?
No. x = 50 is between 0 and 100, but y = 50 is above the top edge (0 + 40 = 40).
Next unit is the final challenge, a game that uses everything including these buttons. Gradio's Button and every phone app do this same work for you. Class ideas: a class control panel with different buttons; design a calculator keypad.