学习笔记PythonPython 海龟绘图:turtle库的使用
小嗷犬turtle 简介
turtle
库是 turtle 绘图体系 Python 的实现,turtle 库是 python 的标准库之一,属于入门级的图形绘制函数库。
turtle 库绘制原理:有一只海龟在窗体正中心,在画布上游走,走过的轨迹形成了绘制的图形,海龟由程序控制,可以自由改变颜色、方向宽度等。
官方文档地址:https://docs.python.org/3/library/turtle.html
turtle 基础知识
画布
画布(canvas)就是 turtle 为我们展开用于绘图区域,我们可以设置它的大小和初始位置。
我们可以通过screensize
函数来设置画布的大小和背景颜色:
1
| turtle.screensize(canvwidth=None, canvheight=None, bg=None)
|
其中screensize
函数的三个参数分别表示画布的宽、高和背景颜色。
或者通过setup
函数来设置:
1
| turtle.setup(width=0.5, height=0.75, startx=None, starty=None)
|
其中参数width
,height
:输入宽和高为整数时, 表示像素;为小数时,表示占据电脑屏幕的比例。
(startx
,starty
): 这一坐标表示矩形窗口左上角顶点的位置,如果为空,则窗口位于屏幕中心。
画笔
画笔的状态
在画布上,默认有一个坐标原点为画布中心的坐标轴,坐标原点上有一只面朝 x 轴正方向小乌龟。
这里我们描述小乌龟时使用了两个词语:坐标原点(位置),面朝 x 轴正方向(方向), turtle 绘图中,就是使用位置方向描述小乌龟(画笔)的状态。
画笔的属性
画笔有宽度、颜色、移动速度三个属性,分别可以通过以下函数来设置:
函数 | 描述 |
---|
turtle.pensize() | 设置画笔的宽度。 |
turtle.pencolor() | 没有参数时,返回当前画笔颜色; 传入参数时,设置画笔颜色。 |
turtle.speed(speed) | 设置画笔移动速度,数字越大越快,当速度为 0 时为最快速。 |
绘图命令
操纵海龟绘图有着许多的命令,这些命令主要可以划分为 3 种:一种为画笔运动命令,一种为画笔控制命令,还有一种是全局控制命令。
画笔运动命令
画笔运动命令如下:
命令 | 描述 |
---|
turtle.forward(distance) | 向当前画笔方向移动 distance 像素长度 |
turtle.backward(distance) | 向当前画笔相反方向移动 distance 像素长度 |
turtle.right(degree) | 顺时针移动 degree° |
turtle.left(degree) | 逆时针移动 degree° |
turtle.pendown() 或 turtle.pd() | 移动时绘制图形,缺省时也为绘制 |
turtle.goto(x,y) | 将画笔移动到坐标为 x,y 的位置 |
turtle.penup() 或 turtle.pu() | 提起笔移动,不绘制图形,用于另起一个地方绘制 |
turtle.circle() | 画圆,半径为正(负),表示圆心在画笔的左边(右边)画圆 |
setx( ) | 将当前 x 轴移动到指定位置 |
sety( ) | 将当前 y 轴移动到指定位置 |
setheading(angle) | 设置当前朝向为 angle 角度 |
home() | 设置当前画笔位置为原点,朝向水平向右 |
dot(r) | 绘制一个指定直径和颜色的圆点 |
值得一提的是circle()
函数:
1
| turtle.circle(radius, extent=None, steps=None)
|
它包含三个参数:
radius
表示半径,半径为正(负),表示圆心在画笔的左边(右边)画圆;extent
表示角度,360 为一个整圆;step
为 3 时,表示绘制三角形。
画笔控制命令
画笔控制命令如下:
命令 | 描述 |
---|
turtle.fillcolor(colorstring) | 绘制图形的填充颜色 |
turtle.color(color1, color2) | 同时设置 pencolor=color1, fillcolor=color2 |
turtle.filling() | 返回当前是否在填充状态 |
turtle.begin_fill() | 准备开始填充图形 |
turtle.end_fill() | 填充完成 |
turtle.hideturtle() | 隐藏画笔的 turtle 形状 |
turtle.showturtle() | 显示画笔的 turtle 形状 |
全局控制命令
全局控制命令如下:
命令 | 描述 |
---|
turtle.clear() | 清空 turtle 窗口,但是 turtle 的位置和状态不会改变 |
turtle.reset() | 清空窗口,重置 turtle 状态为起始状态 |
turtle.undo() | 撤销上一个 turtle 动作 |
turtle.isvisible() | 返回当前 turtle 是否可见 |
stamp() | 复制当前图形 |
turtle.write(s [,font=(“font-name”,font_size,“font_type”)]) | 写文本,s 为文本内容,font 是字体的参数,分别为字体名称,大小和类型;font 为可选项,font 参数也是可选项 |
其他命令
除了上述的三种命令外,turtle 库中还要一些不常用的命令:
命令 | 描述 |
---|
turtle.mainloop()或 turtle.done() | 启动事件循环,调用 Tkinter 的 mainloop 函数。 必须是海龟图形程序中的最后一个语句。 |
turtle.mode(mode=None) | 设置海龟模式(“standard”,“logo”或“world”)并执行重置。如果没有给出模式,则返回当前模式。 |
turtle.delay(delay=None) | 设置或返回以毫秒为单位的绘图延迟。 |
turtle.begin_poly() | 开始记录多边形的顶点。当前的海龟位置是多边形的第一个顶点。 |
turtle.end_poly() | 停止记录多边形的顶点。当前的海龟位置是多边形的最后一个顶点。将与第一个顶点相连。 |
turtle.get_poly() | 返回最后记录的多边形。 |
代码实例
哆啦 A 梦
下面的程序可以绘制出哆啦 A 梦:
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| import turtle
doraemon = turtle.Turtle() doraemon.speed(10)
def draw_eye_white_circle(x): doraemon.goto(x, 80) doraemon.pendown() doraemon.color('black') doraemon.begin_fill() doraemon.circle(15) doraemon.color('white') doraemon.end_fill()
def draw_eye_black_circle(x): doraemon.goto(x, 90) doraemon.color('black') doraemon.begin_fill() doraemon.begin_fill() doraemon.circle(6) doraemon.end_fill() doraemon.penup()
doraemon.color('#0093dd') doraemon.begin_fill() doraemon.circle(60) doraemon.end_fill()
doraemon.begin_fill() doraemon.circle(50) doraemon.color('white') doraemon.end_fill()
draw_eye_white_circle(15)
draw_eye_black_circle(6)
draw_eye_white_circle(-15)
draw_eye_black_circle(-24)
doraemon.goto(0, 60) doraemon.pendown() doraemon.color('#c70000') doraemon.begin_fill() doraemon.circle(8) doraemon.end_fill()
doraemon.color('black')
doraemon.setheading(-90)
doraemon.forward(40) doraemon.penup()
doraemon.goto(-30, 40) doraemon.pendown() doraemon.circle(30, 180) doraemon.penup() doraemon.goto(0, 0)
turtle.Screen().exitonclick()
|
效果图:
动态时钟
下面的程序可以绘制出动态时钟:
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| import turtle from datetime import *
def Skip(step): turtle.penup() turtle.forward(step) turtle.pendown()
def mkHand(name, length): turtle.reset() Skip(-length * 0.1) turtle.begin_poly() turtle.forward(length * 1.1) turtle.end_poly() handForm = turtle.get_poly() turtle.register_shape(name, handForm)
def Init(): global secHand, minHand, hurHand, printer turtle.mode("logo") mkHand("secHand", 135) mkHand("minHand", 125) mkHand("hurHand", 90) secHand = turtle.Turtle() secHand.shape("secHand") minHand = turtle.Turtle() minHand.shape("minHand") hurHand = turtle.Turtle() hurHand.shape("hurHand")
for hand in secHand, minHand, hurHand: hand.shapesize(1, 1, 3) hand.speed(0)
printer = turtle.Turtle() printer.hideturtle() printer.penup()
def SetupClock(radius): turtle.reset() turtle.pensize(7) for i in range(60): Skip(radius) if i % 5 == 0: turtle.forward(20) Skip(-radius - 20)
Skip(radius + 20) if i == 0: turtle.write(int(12), align="center", font=("Courier", 14, "bold")) elif i == 30: Skip(25) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-25) elif (i == 25 or i == 35): Skip(20) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-20) else: turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-radius - 20) else: turtle.dot(5) Skip(-radius) turtle.right(6)
def Week(t): week = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] return week[t.weekday()]
def Date(t): y = t.year m = t.month d = t.day return "%s %d %d" % (y, m, d)
def Tick(): t = datetime.today() second = t.second + t.microsecond * 0.000001 minute = t.minute + second / 60.0 hour = t.hour + minute / 60.0 secHand.setheading(6 * second) minHand.setheading(6 * minute) hurHand.setheading(30 * hour)
turtle.tracer(False) printer.forward(65) printer.write(Week(t), align="center", font=("Courier", 14, "bold")) printer.back(130) printer.write(Date(t), align="center", font=("Courier", 14, "bold")) printer.home() turtle.tracer(True)
turtle.ontimer(Tick, 100)
turtle.tracer(False) Init() SetupClock(160) turtle.tracer(True) Tick() turtle.mainloop()
|
静态效果图:
小樱花树
下面的程序可以绘制出小樱花树:
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import turtle import random
def Tree(branch, t): if branch > 3: if 8 <= branch <= 12: if random.randint(0, 2) == 0: t.color('snow') else: t.color('lightcoral') t.pensize(branch / 3) elif branch < 8: if random.randint(0, 1) == 0: t.color('snow') else: t.color('lightcoral') t.pensize(branch / 2) else: t.color('sienna') t.pensize(branch / 10) t.forward(branch) a = 1.5 * random.random() t.right(20 * a) b = 1.5 * random.random() Tree(branch - 10 * b, t) t.left(40 * a) Tree(branch - 10 * b, t) t.right(20 * a) t.up() t.backward(branch) t.down()
def Petal(m, t): for i in range(m): a = 200 - 400 * random.random() b = 10 - 20 * random.random() t.up() t.forward(b) t.left(90) t.forward(a) t.down() t.color('lightcoral') t.circle(1) t.up() t.backward(a) t.right(90) t.backward(b)
t = turtle.Turtle()
w = turtle.Screen() t.hideturtle() t.getscreen().tracer(5, 0) w.screensize(bg='wheat') t.left(90) t.up() t.backward(150) t.down() t.color('sienna')
Tree(60, t)
Petal(200, t) w.exitonclick()
|
效果图:
飘落樱花树
下面的程序可以绘制出飘落樱花树(绘制时间较长,默认隐藏绘制过程):
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| from turtle import * from random import * from math import *
def tree(n,l): pd() t = cos(radians(heading()+45))/8+0.25 pencolor(t,t,t) pensize(n/3) forward(l)
if n>0: b = random()*15+10 c = random()*15+10 d = l*(random()*0.25+0.7) right(b) tree(n-1,d) left(b+c) tree(n-1,d) right(c) else: right(90) n=cos(radians(heading()-45))/4+0.5 pencolor(n,n*0.8,n*0.8) circle(3) left(90) if(random()>0.7): pu() t = heading() an = -40 +random()*40 setheading(an) dis = int(800*random()*0.5 + 400*random()*0.3 + 200*random()*0.2) forward(dis) setheading(t) pd() right(90) n = cos(radians(heading()-45))/4+0.5 pencolor(n*0.5+0.5,0.4+n*0.4,0.4+n*0.4) circle(2) left(90) pu() t=heading() setheading(an) backward(dis) setheading(t) pu() backward(l)
bgcolor(0.5,0.5,0.5) ht() speed(0) tracer(0,0) pu() backward(100) left(90) pu() backward(300) tree(12,100) done()
|
效果图:
圣诞树
下面的程序可以绘制出圣诞树(绘制时间较长,默认隐藏绘制过程):
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| from turtle import * import random
n = 100.0
speed(0) screensize(bg='seashell') tracer(0, 0) left(90) forward(3*n) color("orange", "yellow") begin_fill() left(126)
for i in range(5): forward(n/5) right(144) forward(n/5) left(72) end_fill() right(126)
color("dark green") backward(n*4.8) def tree(d, s): if d <= 0: return forward(s) tree(d-1, s*.8) right(120) tree(d-3, s*.5) right(120) tree(d-3, s*.5) right(120) backward(s) tree(15, n) backward(n/2)
for i in range(200): a = 200 - 400 * random.random() b = 10 - 20 * random.random() up() forward(b) left(90) forward(a) down() if random.randint(0, 1) == 0: color('tomato') else: color('wheat') circle(2) up() backward(a) right(90) backward(b)
done()
|
效果图: