Download presentation
Presentation is loading. Please wait.
1
计算机编程导论 -Python语言 第5讲 图形编程 讲课教师:常姗
2
有图有真相 应用程序经常要用到图形/图像/动画
统计软件 证券分析软件 教学软件 可视化(visualization):将抽象事物和过程转变 成视觉可见的、形象直观的图形图像表示 柱状图,直方图,散点图,网络图,流程图,树,地图,图 像,动画,...
3
计算可视化 科学可视化:将科学与工程计算、实验中的数据 用直观的计算机图形图像呈现出来,以便人们理 解数据、增强对事物现象的认识和对内在规律的 洞察. 数据可视化:将海量数据转化为数据图像,以帮 助人们直观地观察数据. 可以进而发展到更高层次 的信息可视化和知识可视化. 工程设计可视化 ...
4
图形是复杂数据 包含的信息是复杂的 图形操作是复杂的 圆形:圆心(元组)和半径(数值);内部 及边界的颜色(RGB元组);...
求面积,周长等传统计算;还有移动位 置,改颜色等等 A:如何表示图 形这一类的复 杂数据、如何 操作这类复杂 数据呢? 4
5
数据,revisit(1) 编程:数据表示+操作过程 每种数据类型包含一个合法值的集合,以及一个合法运算的集合
数据表示:编程语言已提供了一些数据类型,例如: 字符串-雇员姓名,整数-年龄,浮点数-工资 雇员名单-字符串数据构成的列表 数据操作:各种数据类型所支持的数据操作来处理数据 ,例如: 工资-加减乘除,姓名-抽取姓和名 每种数据类型包含一个合法值的集合,以及一个合法运算的集合
6
数据,revisit(2) 先考虑数据的表示,再考虑对数据的操作 数据和对数据的操作被看作是两件相互分离的事 信息 解法 现实世界问题 数据
处理 机器世界程序
7
数据,revisit(3) 例如:输入三边长,判断该三个边能否构成三角形,如 能,则将三角形的周长与面积在屏幕输出。 面向过程 自顶向下
先获得边长数据,再判断数据合法性,求周长,面积 面向过程 自顶向下 main result a,b,c a,b,c a,b,c GetEdges GetArea IsTriangle a,b,c GetPerimeter
8
对象(object) 将数据和对数据的操作视为不可分离 两者组合在一起形成一个实体——对象
面向对象术语中,对象的数据称为属性,对象的 操作称为方法。 事物 (状态,行为) 现实世界问题 对象 (属性,操作) 机器世界程序
9
对象 例如:输入三边长,判断该三个边能否构成三角形,如 能,则将三角形的周长与面积在屏幕输出。 a, b, c 对象:Triangle
数据 a, b, c 对象:Triangle IsTriangle() GetPerimeter() GetArea() 操作 图形应用程序非常适合采用面向对象概念。
10
Python图形库 Tkinter Python 自带的一个标准模块,是一个功能强大的图形用户界面工具包,能够用来开发像Windows应用程序一样具有窗口、菜单、按钮等图形构件的程序。
11
Tkinter图形编程(1) 导入模块 创建根窗口:作图窗口
import Tkinter 或 from Tkinter import * 创建根窗口:作图窗口 root = Tk() 根窗口 根窗口实际上是一个对象,它有自己的属性(如宽度、高度、窗口标题),也有自己的方法。
12
Tkinter图形编程(2) 创建画布对象 例如:在root中创建300x200的白色画布
c = Canvas(<窗口>,<选项1>=<值1>,...) Canvas是画布类(class),利用它可创建画布对象 在<窗口>中创建画布 <选项>=<值>用来设置画布对象的数据,如高度,宽度, 背景色等 例如:在root中创建300x200的白色画布 c = Canvas(root, width=300,height=200,bg=‘white') 12 12 12
13
Tkinter图形编程(3) 布置画布 在面向对象编程中,对对象中的数据执行操作, 采用点表示法——“对象.操作”。
已经创建了画布c,但在窗口 root中看不见,因为还需要将 画布"布置"到窗口中. >>> c.pack() 在面向对象编程中,对对象中的数据执行操作, 采用点表示法——“对象.操作”。 c.pack()中,变量c代表Canvas对象,pack()是c 能够响应的一个方法。 c.pack()表示向对象c发出执行pack()方法的请求。 13 13
14
Tkinter图形编程(4) 画布上的坐标系 坐标单位是像素 也可用厘米(c),英寸(i)等.
画布左上角原点坐标为(0,0), 300x200的画布右下角坐标为(299,199) 也可用厘米(c),英寸(i)等. c.pack()表示请画布c执行"pack布局"操作
15
c.create_rectangle(x0,y0,x1,y1,<选项>...)
Tkinter图形编程(5) 在画布上绘图,例如: 画布对象提供create_rectangle()方法,用于在画布上创建矩形。 c.create_rectangle(x0,y0,x1,y1,<选项>...) 矩形的位置和大小由两点定义: (x0,y0)给出矩形的左上角,(x1,y1)给出矩形的右下角 返回值是所创建的矩形的标识号 常用选项 outline = 颜色 fill = 颜色 state=NORMAL/HIDDEN dash=(线段长,间隔) >>> c.create_rectangle(50,50,200,100)
16
图形项标示 画布上的图形 都有标识号,用于区分同一画布上的多个图形,
自动创建,唯一 >>> id=c.create_rectangle(50,50,200,100) 也可以为图形命名(标签) 字符串型 允许1对多,多对1
17
指定标签 在创建图形时利用选项tags来指定 图形创建后,用画布的itemconfig()方法来设置
可指定单个字符串,或一个字符串元组(多个名字) r1 =c.create_rectangle(20,20,100,80,tags="#1") r2 = c.create_rectangle(40,50,200,180,tags=("myRect","#2")) 图形创建后,用画布的itemconfig()方法来设置 c.itemconfig(r1,tags=("myRect","rectOne")) 用画布的addtag_withtag()方法为图形项增添新标签 c.addtag_withtag("ourRect","rectOne")
18
画布对象的方法(1) 删除画布上的图形 移动画布上的图形 设置画布上图形的选项 c.delete(id) id是画布上图形的标识号
c.move(id,dx,dy) id是图形标识号,dx和dy是轴向移动距离 设置画布上图形的选项 c.itemconfig(id,<选项>=<值>...)
19
例:画矩形 坐标存储在变量中的做法是值得推荐的!
>>> c.create_rectangle(50,50,200,100) 1 >>> r2 = c.create_rectangle(80,70,240,150,tags="rect#2") >>> print r2 2 >>> c.itemconfig(1,fill="black") >>> c.itemconfig(r2,fil1="grey",outline="white",width=6) >>> c.delete(r2) >>> c.move(1,50,50) >>> c.create_rectangle(50,50,51,51) # Tkinter画点 >>> p1 = (10,10) >>> p2 = (50,80) >>> c.create_rectangle(p1,p2,tags="#3") >>> xy = (100,110,200,220) >>> c.create_rectangle(xy) 坐标存储在变量中的做法是值得推荐的!
20
c.create_oval(x0,y0,x1,y1,<选项>...) 限定框(bounding box),即外接矩形
画布对象的方法(2) 画椭圆 c.create_oval(x0,y0,x1,y1,<选项>...) 返回所画椭圆的标识号 常用选项 outline = 颜色 fill = 颜色 state=NORMAL/HIDDEN dash=(线段长,间隔) 限定框(bounding box),即外接矩形
21
例:画椭圆 >>> o1 = c.create_oval(50,50,250,150) >>> o2 = c.create_oval(110,85,140,115,fill='red') >>> o3 = c.create_oval(245,95,255,105,fill='blue')
22
画布对象的方法(3) 画弧形 c.create_arc(x0,y0,x1,y1,<选项>...) 返回所画弧形的标识号 常用选项
start=开始位置(角度) extent=逆时针旋转的角度 style=PIESLICE/ARC/CHORD outline, fill, state, dash等 PIESLICE CHORD ARC
23
例:画弧形 >>> bbox = (50,50,250,150) >>> c.create_arc(bbox) >>> c.create_arc(bbox,start=100,extent=140,style="arc", width=4) >>> c.create_arc(bbox,start=250,extent=110,style="chord")
24
c.create_line(x0,y0,...xn,yn,<选项>...)
画布对象的方法(4) 画线条 c.create_line(x0,y0,...xn,yn,<选项>...) 返回所画线条的标识号 常用选项 smooth=0:折线/非0:平滑曲线 arrow=NONE/FIRST/LAST/BOTH arrowshape=(d1,d2,d3) fill, state, dash等
25
例:画北斗七星和北极星 >>> s1 = (20,20) >>> s2 = (60,40) >>> s3 = (80,60) >>> s4 = (85,80) >>> s5 = (70,100) >>> s6 = (85,115) >>> s7 = (110,100) >>> polaris = (220,40) >>> c.create_oval(s1,(23,23),fill='black') >>> c.create_oval(s2,(63,43),fill='black') ... >>> c.create_oval(s7,(113,103),fill='black') >>> c.create_oval((222,36),(226,42),fill='black') >>> c.create_line(s1,s2,s3,s4,s5,s6,s7,s4) >>> c.create_line(s7,polaris,dash=(4,),arrow=LAST) >>> c.create_line(5,190,150,160,295,190,smooth=1)
26
画布对象的方法(5) 画多边形 c.create_polygon(x0,y0,...xn,yn,<选项>...)
返回所画多边形的标识号 常用选项 smooth=0:折线/非0:平滑曲线 outline(缺省值为空) fill(缺省值为黑色) state, dash等
27
例:画多边形 >>> p11,p21,p31 = (70,20),(70+100,20),(70,20+100) >>> p12,p22,p32 = (35,50),(35+100,50),(35,50+100) >>> p13,p23,p33 = (55,85),(55+100,85),(55,85+100) >>> p14,p24,p34 = (85,85),(85+100,85),(85,85+100) >>> p15,p25,p35 = (105,50),( ,50),(105,50+100) >>> c.create_polygon(p11,p12,p13,p14,p15) >>> c.create_polygon(p21,p23,p25,p22,p24,outline="black",fill="") >>> c.create_polygon(p31,p32,p33,p34,p35,outline="black",fill="")
28
画布对象的方法(6) 创建文本 c.create_text(x,y,<选项>...) 返回所创建文本的标识号 常用选项
anchor=E/S/W/N/CENTER/SE/NE/... justify=LEFT/CENTER/RIGHT(文本对齐方式) width 超过则换行 fill, state, dash等
29
例:创建文本 >>> t1 = >>> >>> >>> >>> Line")
30
画布对象的方法(7) 创建图像 img = PhotoImage(file = <gif图像文件名>)
先创建图像对象 img = PhotoImage(file = <gif图像文件名>) 在画布上显示图像对象 c.create_image(x,y,image=img,<选项>...) 返回所创建图像的标识号 常用选项 anchor=E/S/W/N/CENTER/SE/NE/... state, tags等
31
例:创建图像 >>> pic = PhotoImage(file="C:\WINDOWS\Web\exclam.gif") >>> c.create_image(150,100,image=pic)
32
事件编程 def canvasFunc(event): if c.itemcget(t,"text") == "Hello!": c.itemconfig(t,text="Goodbye!") else: c.itemconfig(t,text="Hello!") def textFunc(event): if c.itemcget(t,"fill") != "white": c.itemconfig(t,fill="white") c.itemconfig(t,fill="black") ... t = c.create_text(150,100,text="Hello!") c.bind("<Button-1>",canvasFunc) #画布与左键绑定 c.tag_bind(t,"<Button-3>",textFunc) #画布上文本与右键绑定 root.mainloop()
33
编程案例:统计图表(1) 程序规格 算法 输入:考试分数 输出:以饼图表示的各分数段所占比例
输入分数mark,换算成a,b,c,d,f等级并累加该等级的人数; 创建窗口和画布; 计算各等级的比例(a/n等),并据此确定扇形起止角度(sA,eA等); 绘制各扇形; 绘制图例; *为各扇形绑定“鼠标进入”事件,并定义事件处理函数(inPieA()等); *进入主事件循环。
34
编程案例:统计图表(2) 代码实现:piechart.py
35
动画编程 动画:运动的图形. 计算机动画 现实中运动是连续的. 运动离散化:t, t+∆t, t+2∆t, t+3∆t,...
快速交替显示一组静止图形,或让一幅图形快速移动. 关键是控制交替显示或移动的速度:24帧/秒
36
编程实例:演示天体运动(1) 地球在椭圆轨道上运动的计算: 画布坐标系中:
37
编程实例:演示天体运动(2) 月球一方面随地球绕太阳运动,一方面还绕地球 运动. 分别计算两种运动导致的坐标变化,然后求和.
月球一方面随地球绕太阳运动,一方面还绕地球 运动. 分别计算两种运动导致的坐标变化,然后求和. 月球绕地球的旋转速度大约是地球绕太阳的旋转速度 的12 倍(一年有十二个月)。
38
编程实例:演示天体运动(3) 每次循环中修改图形位置后都必须执行一个更新画布显示的方法c.update(),以使新画面显示出来;
两个画面之间的停顿可以用time 模块中的sleep()函数来实现,该函数的作用就是让程序休眠一会(参数以秒为单位)。 算法 创建窗口和画布; 在画布上绘制太阳、地球和月球,以及地球的绕日椭圆轨道; 设置地球和月球的当前位置; 进入动画循环: 旋转0.01 计算地球和月球的新位置 移动地球和月球到新位置 更新地球和月球的当前位置; 停顿一会 程序:animation.py
39
软件的层次化设计 在一层软件之上架设另一层软件,即高层软件的功能是由 低层软件实现的. 例如 为什么不直接使用低层软件?
通常低层软件的界面比较复杂,不适合普通用户使用. 例如
40
层次化设计案例:graphics 有人在Tkinter之上设计了另一个图形模块graphics.py
这是非标准模块,需要自己下载
41
海龟作图 turtle模块 import turtle 创建画布 t=turtle.Pen() 移动海龟
t.forward(a) #向前爬行a像素 t.backward(a) #向后退a像素 t.left(a) #向左转a度 t.right(a)#向右转a度 t.up()#画笔抬起,海龟停止作画 t.down()#画笔落下,开始作画 t.reset()#清除画布,海龟放回原位置 t.clear() #清除画布,海龟留在原位
42
海龟作图-星星 >>> t.reset() >>> for x in range(1,9): t.forward(300) t.left(225) >>> t.reset() >>> for x in range(1,38): t.forward(300) t.left(175) >>> t.reset() >>> for x in range(1,20): t.forward(300) t.left(95)
43
海龟作图-填色 begin_fill(),end_fill()定义填充区域 color函数设置画笔颜色
color(Red, Green, Blue) 参数的值:0~1 color(0, 0, 0)黑色 color(1, 1, 1)白色 例: import turtle t=turtle.Pen() def mysquare(size, filled): if filled == True: t.begin_fill() for x in range(1,5): t.forward(size) t.left(90) t.end_fill() mysquare(100,True) mysquare(300,False)
44
练习与作业 程序设计:画一个射箭运动所用的箭靶。从小到大分别 为黄、红、蓝、黑、白色的同心圆,每个环的宽度都等 于黄色圆形的半径。
程序设计:绘制奥运五环旗。 程序设计:输入本金和利率,计算10 年内每一年的本 金加利息之和,并用柱状图显示。 程序设计:画一幅冬季景色,有雪人和圣诞树之类。
45
作业解析(1) 编程序,从函数输入一个字符串,将字符串中的数字删除,并将大写改为小 写,最后的结果在函数中打印。例如输入Abc123De4f,则输出abcdef。 import string def if_string(s): for i in s: if i not in string.letters + string.digits: return False return True def change_string(s): s_new = '' s_ch = string.lower(s) for i in s_ch: if i in string.letters: s_new += i return s_new def main(): s = raw_input('Please input:') if if_string(s): print change_string(s) else: print 'Error!!!' main()
46
作业解析(2) 假定输入字符串中只包含字母和*号,请编写函数fun,它的功能是将字符串 中间的*号删除,前面和后面不删除。结果在函数中打印。例如输入字符串 的内容为***a**b**c*d***,则输出***abcd***。 import string def if_string(s): for i in s: if i not in string.letters + '*': return False return True def change_string(s): s_new = '‘ s_list = list(s) s_temp = [] for i in range(len(s_list)): if s_list[i] in string.letters: s_temp.append(i) for i in s_temp: s_new += s_list[i] s_new = ('*' * s_temp[0]) + s_new + ('*' * (len(s_list) - s_temp[-1] - 1)) return s_new def main(): s = raw_input('Please input:') if if_string(s): print change_string(s) else: print 'Error!!!' main()
47
作业解析(2) 解法2 def change_string(s): s_new = '' s_list = list(s)
i,j = 0,-1 while i < len(s_list): if s_list[i]=="*": i+=1 else: break begin_char=i while j >= -len(s_list): if s_list[j]=="*": j-=1 end_char=j+1 for x in s_list[begin_char:end_char]: if x in string.letters: s_new+=x s_new = ('*' * begin_char) + s_new + ('*' * abs(end_char)) return s_new 解法2
48
作业解析(3) 编写函数,输入年、月、日,计算该日是该年的第几天 (注意判别闰年)。 求和函数,参数是一个list
def input_f(): year = input('Please input year:') month = input('Please input month:') day = input('Please input day:') return year, month, day def day_in_year(year, month, day): mon = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if (year % 400 == 0) or ((year % 4 == 0) & (year % 100 != 0)): if month > 2: return int(sum(mon[:month - 1])) + day + 1 else: return int(sum(mon[:month - 1])) + day def main(): year, month, day = input_f() the_day = day_in_year(year, month, day) print year, month, day, '\nThis day is', the_day, 'day in year', year main() 求和函数,参数是一个list
49
join(list,sep) -> string 用sep分隔list中元素,sep缺省值为空格
作业解析(4) 从函数输入一个字符串,将字符串中索引为偶数,同时ASCII为奇字符后面 加*号,新生成的字符串在函数中打印。例如,输入字符串ABCDEFG12345 ,则打印A*BC*DE*FG*12345。 import string def change_string(s): count = 0 s_list = list(s) s_list_temp = s_list[:] for i in range(0, len(s_list_temp), 2): if ord(s_list_temp[i]) % 2 == 1: s_list.insert(i count, '*') count += 1 s_new = join(s_list,'') return s_new def main(): s = raw_input('Please input:') print change_string(s) main() join(list,sep) -> string 用sep分隔list中元素,sep缺省值为空格
50
split(str,sep) -> list of strings
作业解析(5) 统计字符串中的单词个数。例如输入I am a boy! 则返回单词个数为4。 import string str = raw_input('Please input:') list=string.split(str,' ') print list print len(list), 'words' split(str,sep) -> list of strings 根据sep来对字符串中元素进行分割
51
作业解析(6) 一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个 数本身,则称其为花朵数。(n=3时称为“水仙花”数。)编程序,输入n, 输出n位的全部花朵数。 def if_num(n, p): n = str(n) n_list = list(n) s = 0 for i in n_list: s += int(i) ** p if s == int(n): print n def main(): p = input('Please in put a number:') for n in range(10 ** (p - 1), 10 ** p - 1): if_num(n, p) main()
Similar presentations