Learning Goals
3 minBy the end of this lesson you can:
- Set the pen colour with a name (
"tomato") or an RGB triple ((255, 99, 71)). - Fill any closed shape with
begin_fill()...end_fill(). - Use a palette list to colour successive iterations differently.
- Switch between dotted, dashed and solid strokes via
pensize.
Warm-Up · Three Ways to Pick a Colour
5 minimport turtle as t t.color("red") # named t.color("#FF6347") # hex t.colormode(255) # tell turtle we'll use 0-255 RGB t.color((255, 99, 71)) # RGB triple — same colour, three ways
Turtle's default colour mode uses 0-1 floats. Switch to 255 with colormode(255) if you prefer the standard CSS/photo-editor scale.
Colour and fill turn line drawings into illustrations. Two extra calls (begin_fill, end_fill) is all it takes.
New Concept · Fill, Palette, Stroke
14 minFilling a closed shape
Wrap the shape's drawing code with begin_fill and end_fill. The interior is flooded with the current fill colour.
import turtle as t t.color("black", "tomato") # (pen, fill) t.begin_fill() for _ in range(5): # pentagon t.forward(80) t.right(72) t.end_fill()
color(a, b) sets pen to a and fill to b in one call. Otherwise use pencolor and fillcolor separately.
Palettes from a list
Loop over a palette to colour each iteration of a pattern.
palette = ["crimson", "orange", "gold", "limegreen", "skyblue", "violet"] for i in range(24): t.color(palette[i % len(palette)]) polygon(6, 60) t.right(360 / 24)
i % len(palette) cycles 0, 1, 2, ..., back to 0 — "wrap-around indexing". Each petal gets the next colour; once the palette ends, it loops back to the first.
Filling inside a rosette
Each iteration can have its own filled shape — call begin_fill / end_fill around the inner draw:
for i in range(24): t.fillcolor(palette[i % len(palette)]) t.begin_fill() for _ in range(6): t.forward(60); t.right(60) t.end_fill() t.right(360 / 24)
Pen size and stroke styles
Make the line thicker, or break it into dashes.
t.pensize(5) # thick line t.pencolor("steelblue") # "Dashed" stroke — alternate penup/pendown in a loop t.penup() t.goto(-200, 0) t.setheading(0) t.pendown() for _ in range(20): t.forward(10); t.penup(); t.forward(10); t.pendown()
There's no built-in dashed-line setting. The dash trick — alternate down/up on a fixed forward step — gives you dotted, dashed or whatever pattern you like.
Custom RGB
For full control, mix your own colours:
t.colormode(255) t.bgcolor((30, 30, 60)) # near-black dark blue t.color((255, 200, 0)) # warm gold # Hex strings also work t.color("#FF6347") # tomato
The dunno-which-colour-to-pick problem
Use one of these palettes when you can't decide:
Warm sunset crimson, orange, gold Pastel lightcoral, peachpuff, lavender, mediumturquoise Neon magenta, cyan, lime, yellow Earth sienna, olive, forestgreen, tan Monochrome #0a0a0a, #2c2c2c, #5c5c5c, #a0a0a0, #f0f0f0
Worked Example · The Colour Rosette
12 minSave as colour_rosette.py:
# colour_rosette.py — filled rosette with a palette import turtle as t palette = [ "crimson", "orangered", "gold", "olive", "forestgreen", "teal", "royalblue", "purple", ] t.speed(0) t.bgcolor("black") t.pencolor("white") t.pensize(2) PETALS = 16 for i in range(PETALS): t.fillcolor(palette[i % len(palette)]) t.begin_fill() for _ in range(5): t.forward(120) t.right(72) t.end_fill() t.right(360 / PETALS) t.done()
What you'll see
Sixteen pentagons fanned around the centre. Each one filled with the next colour from the palette, cycling through twice (since the palette has 8 and we're drawing 16). The white outline gives every petal a clean edge.
Read the diff
Compared to PY-L2-34's rosette: two new calls — begin_fill and end_fill — around the inner polygon, and a palette list indexed by i % len(palette). Three tiny additions; the visual upgrade is enormous.
Try It Yourself
13 minDraw a green square with a black outline, 150 units on a side.
Hint
import turtle as t t.color("black", "forestgreen") t.begin_fill() for _ in range(4): t.forward(150); t.right(90) t.end_fill() t.done()
Draw three filled circles stacked vertically — red, yellow, green. Use t.circle(radius) for each. Lift the pen between them so they don't connect.
Hint
import turtle as t for colour, y in [("red", 80), ("gold", 0), ("forestgreen", -80)]: t.penup(); t.goto(0, y); t.pendown() t.color("black", colour) t.begin_fill() t.circle(40) t.end_fill() t.done()
t.circle(r) draws a circle of radius r starting at the current position, going anticlockwise.
Make a spiral where every step is a different colour from a palette of seven.
Hint
import turtle as t rainbow = ["red", "orange", "gold", "limegreen", "skyblue", "blue", "purple"] t.speed(0); t.bgcolor("black"); t.pensize(3) for n in range(60): t.pencolor(rainbow[n % 7]) t.forward(n * 4) t.right(91) t.done()
Per-iteration colour + a slight twist (91° not 90°) = a glowing pinwheel.
Mini-Challenge · The Malaysian Flag
8 minBuild flag.py that draws a simplified Jalur Gemilang — alternating red and white stripes, a blue rectangle in the top-left corner. Don't worry about the crescent and star (those need t.circle arcs); just the stripes.
Rules:
- 14 horizontal stripes, each
SCREEN_WIDTHwide and20tall. - Odd stripes red (
"crimson"), even stripes white. - Top-left rectangle is dark blue, half the width and 8 stripes tall.
Show one possible solution
# flag.py — Jalur Gemilang (stripes only) import turtle as t WIDTH = 560 STRIPE = 20 N_STRIPES = 14 t.speed(0) t.hideturtle() def filled_rect(x, y, w, h, colour): t.penup(); t.goto(x, y); t.setheading(0); t.pendown() t.color("black", colour); t.begin_fill() for dx, dy in [(w, 0), (0, -h), (-w, 0), (0, h)]: # not used — we use forward/right pass for _ in range(2): t.forward(w); t.right(90) t.forward(h); t.right(90) t.end_fill() # Stripes top_y = STRIPE * N_STRIPES / 2 for i in range(N_STRIPES): y = top_y - i * STRIPE colour = "crimson" if i % 2 == 0 else "white" filled_rect(-WIDTH/2, y, WIDTH, STRIPE, colour) # Blue canton filled_rect(-WIDTH/2, top_y, WIDTH/2, STRIPE * 8, "midnightblue") t.done()
Non-negotiables: a reusable filled_rect helper, a loop for the stripes, a single call for the blue canton. The crescent and star require arcs — try them as a personal stretch with t.circle(r, extent).
Recap
3 minColour the pen with a name, hex string or RGB triple (after colormode(255)). Fill a closed shape by bracketing it with begin_fill / end_fill. Cycle a palette inside a loop using palette[i % len(palette)]. Adjust strokes with pensize, and fake dashes by alternating penup/pendown on a fixed forward step. Three knobs — colour, fill, stroke — and your patterns from yesterday turn into illustrations.
Vocabulary Card
- begin_fill / end_fill
- Bracket a closed shape; Python floods the inside with the fill colour.
- colormode(255)
- Switch RGB scale from 0-1 to 0-255 — the everyday photo/CSS scale.
- palette cycling
palette[i % len(palette)]picks the next colour and wraps round.- pencolor vs fillcolor
- The outline colour vs the fill colour.
color(a, b)sets both at once.
Homework
4 minBuild album.py — a single file that draws four mini-pictures in the four quadrants of the screen:
- Top-left: a filled hexagon.
- Top-right: a coloured spiral.
- Bottom-left: a 6-petal rainbow rosette (filled).
- Bottom-right: a thick dashed border around an empty square.
Use penup/goto to position each in its quadrant. Pick a coloured background.
Sample · album.py
# album.py — four mini-pictures in four quadrants import turtle as t t.speed(0) t.bgcolor("ivory") t.hideturtle() def jump(x, y): t.penup(); t.goto(x, y); t.setheading(0); t.pendown() # 1 — filled hexagon jump(-200, 100) t.color("black", "tomato"); t.begin_fill() for _ in range(6): t.forward(60); t.right(60) t.end_fill() # 2 — coloured spiral jump(150, 100) t.color("steelblue"); t.pensize(2) for n in range(40): t.forward(n * 2); t.right(91) t.pensize(1) # 3 — 6-petal rosette (filled) jump(-150, -100) palette = ["crimson", "orange", "gold", "limegreen", "skyblue", "purple"] for i in range(6): t.fillcolor(palette[i]); t.begin_fill() for _ in range(4): t.forward(50); t.right(90) t.end_fill() t.right(60) # 4 — dashed border square jump(100, -150) t.color("black"); t.pensize(4) for _ in range(4): for _ in range(10): t.forward(8); t.penup(); t.forward(4); t.pendown() t.right(90) t.pensize(1) t.done()
Non-negotiables: jump helper, four distinct sub-drawings, palette use, fill brackets, and at least one dashed stroke. Each quadrant is its own tiny composition.