Turtle has no buttons, so build one from a rectangle and a click check.
Frameworks give you a button in one line. Underneath, it is a rectangle, a label and a check that a click landed inside. You are about to build all three.
A button is not magic. It is a rectangle, a label, and a check that asks: did the click land inside the rectangle?
Click the picture once before you use it, and press Stop when you are done.
Make your prediction first. Help opens once you've locked it in.
from turtle import *
speed(0)
hideturtle()
bx = -60
by = -25
bw = 120
bh = 50
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("Press me")
def clicked(x, y):
if x > bx and x < bx + bw and y > by and y < by + bh:
print("button pressed")
else:
print("missed")
onscreenclick(clicked)
listen()
mainloop()
The button's corner is at (bx, by). It is bw wide and bh high. A click at (x, y) is inside when x is between bx and bx + bw, and y is between by and by + bh.
Run it, click inside the button and outside it, then press Stop.
from turtle import *
speed(0)
hideturtle()
bx = -60
by = -25
bw = 120
bh = 50
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("Press me")
def clicked(x, y):
if x > bx and x < bx + bw and y > by and y < by + bh:
print("button pressed")
else:
print("missed")
onscreenclick(clicked)
listen()
mainloop()
The program above counts presses. draw_scene redraws everything, and clicked checks the click.
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 + 1
draw_scene()
draw_scene()
onscreenclick(clicked)
listen()
mainloop()
Work out which clicks are inside the button.
Use the numbers to find an edge.
Here is a version where something is wrong.
The button runs from x = -60 to 60 and y = -25 to 25. Fill in whether each click is inside.
| click x | click y | inside? |
|---|---|---|
| 0 | 0 | yes |
| 80 | 0 | |
| -30 | 20 | |
| 10 | 40 |
A button has bx = -60 and bw = 120. What is the largest x that counts as the right edge?
Every click counts as a press, even one far from the button. Click the wrong line.
Make the button bigger and move it to a new place.
Change bx, by, bw and bh at the top. The click check uses the same names, so it follows.
Make each click add 5 instead of 1.
Change the line inside clicked that adds to count.
To add 5, use count = count + 5.
Change what a click does, and keep the counter.
Run your program. This ticks when your code does all of the above.
Work this out on paper first.
# the button covers x from 0 to 100
def clicked(x, y):
if x >= 0 and x <= 100:
print("pressed")
The student clicks at x = 120. How many times does "pressed" appear?
Build a counter with two buttons: +1 on the left and -1 on the right, with the number shown above.
Write one function that draws a button at a given place, and call it twice.
In clicked, use two separate if statements, one for each button. Change count by +1 or -1.
Build a two-button counter.
Run your program. This ticks when your code does all of the above.
A control panel is a list of buttons. This program keeps the button names in a list, draws one button for each with a loop, and uses a loop in clicked to find which one was pressed. Add "lightgreen" to the list and see a fifth button appear. Then change the panel so the buttons sit in two rows.
You wrote the drawing and the click check by hand. Real programs keep them in a module. ui holds both as functions: draw_button and inside. Use them to add a second button that takes one away. Compare how many lines this took with your hand-built version.
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. About 55 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
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.
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.
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.