550 likes | 635 Views
程序设计思想与方法 (5a) 图形界面编程. 赵 海 计算机科学与工程系 上海交通大学 zhaohai @cs.sjtu.edu.cn. 学习目标. 理解对象的概念,以及它如何能用于简化编程。 熟悉图形库 ( 模块 ) 中的各种对象。 能在编程中创建对象并调用合适的方法完成图形计算。. 学习目标. 理解计算机图形学的基础概念,特别是坐标系统和坐标变换 。 在图形编程中,理解如何使用鼠标和文本输入。 能够用图形库编写简单的交互图形程序。. 概要. 每种数据类型能代表一组值,并且具备一组关联的操作运算。 传统的编程观点认为,数据是被动的,它由主动的操作运算来控制。.
E N D
程序设计思想与方法 (5a)图形界面编程 赵 海计算机科学与工程系 上海交通大学zhaohai@cs.sjtu.edu.cn
学习目标 • 理解对象的概念,以及它如何能用于简化编程。 • 熟悉图形库(模块)中的各种对象。 • 能在编程中创建对象并调用合适的方法完成图形计算。
学习目标 • 理解计算机图形学的基础概念,特别是坐标系统和坐标变换 。 • 在图形编程中,理解如何使用鼠标和文本输入。 • 能够用图形库编写简单的交互图形程序。
概要 • 每种数据类型能代表一组值,并且具备一组关联的操作运算。 • 传统的编程观点认为,数据是被动的,它由主动的操作运算来控制。
概要 • 现代计算机程序使用面向对象的(object-oriented)方法来构建。 • 你熟悉的应用程序都具有图形用户界面(接口)( Graphical User Interfaces,GUI),提供视窗、图标、按钮和菜单等元素。 • 本教材专门提供一个图形库 (graphics.py) ,它基于 Tkinter书写.
对象(objects)的目的、作用 • 基本思路 – 视一个复杂系统为一些简单对象的交互。一个对象是一类活跃的数据类型,它结合了数据和上面的操作。 • 对象知道一些事情 (包含数据) ,并且,它能做一些事情 (具备操作). • [图形]对象之间的交互通过彼此发送消息(messages)来实现。
对象(objects)的目的 • 假定我们要给一个大学开发一个数据处理系统。 • 我们需要维护入学的学生的纪录。每个学生可以表示为一个对象。
对象(objects)的目的 • 学生对象将包含如下数据: • 姓名 • 学生证号 • 选修的课程 • 宿舍地址 • 家庭地址 • GPA • 等等.
对象(objects)的目的 • 学生对象应能对处理请求作出相应。 • 我们可能想发出一个全校范围的邮件,因此,我们需要每个学生的宿舍地址。 • 我们能发送 printCampusAddress消息给每个学生对象。 当学生对象接到这个消息后,它能打印自己的地址。
对象(objects)的目的 • 对象可以引用其它对象。 • 每个课程可以表示为一个对象: • 授课教师 • 学生名单 • 先修课程 • 上课时间和地点
对象(objects)的目的 • 操作示例 • addStudent • delStudent • changeRoom • 等等
简单的图形编程 • 使用图形库graphics.py。 • 图形库的位置: • Python的库目录(文件夹),和其它库文件在一起。 • 和你的图形程序在同一目录。
简单的图形编程 • 我们首先需要按照模块导入这个库>>> import graphics • 一个图形窗口是一个屏幕区域,所要展现的图形将出现其中。>>> win = graphics.GraphWin() • 该命令生成一个新的窗口,题为 “Graphics Window.”
简单的图形编程 • GraphWin是一个分配给变量win的对象。 我们能通过这个变量来操作这个对象,类似于通过文件句柄来操作文件。 • 窗口能被如下的命令关闭或者销毁 >>> win.close()
简单的图形界面编程 • 每次调用图形库中的函数都要使用标识graphics.是一件很麻烦的事 • from graphics import *“from”命令允许你从模块库中加载相应的函数。 “*” 是加载所有函数;或者你也可以选择加载自己指定的函数.
简单的图形界面编程 • 像这样使用import 命令可以消除在调用图形库函数之前一定要添加的前缀标识 graphics.>>> from graphics import *>>> win = GraphWin()
简单的图形界面编程 • 一个图形界面窗口是由像素点组成的,像素是图形的基本组成要素。 • 默认的GraphWin是200 像素高,200 像素宽 (一共40,000). • 一个在窗口中绘制图形的方法就是一次画一个像素点。但是这太麻烦了,图形库有很多事先定义好的函数可以直接绘制几何图形。
简单的图形界面编程 • 最简单的对象是 Point。与几何中的点的表示一样, 点的坐标由坐标系统(x, y)表示, 其中x是横坐标,y是纵坐标. • 图形窗口中的原点 (0,0)在窗口的左上角. • X 的值从左往右增大, y 的值从上往下增大. • 右下角的坐标是 (199, 199)
简单的图形界面编程 >>> p = Point(50, 60) >>> p.getX() 50 >>> p.getY() 60 >>> win = GraphWin() >>> p.draw(win) >>> p2 = Point(140, 100) >>> p2.draw(win)
简单的图形界面编程 >>> ### 打开一个图形窗口 >>> win = GraphWin('Shapes') >>> ### 绘制一个圆点在(100, 100)半径是30的红色的圆 >>> center = Point(100, 100) >>> circ = Circle(center, 30) >>> circ.setFill('red') >>> circ.draw(win) >>> ### 在圆的中心绘制一个文字标签 >>> label = Text(center, "Red Circle") >>> label.draw(win) >>> ### 使用Rectangle对象绘制一个正方形 >>> rect = Rectangle(Point(30, 30), Point(70, 70)) >>> rect.draw(win) >>> ### 使用Line对象绘制一条线段 >>> line = Line(Point(20, 30), Point(180, 165)) >>> line.draw(win) >>> ### 使用Oval绘制一个椭圆 >>> oval = Oval(Point(20, 150), Point(180, 199)) >>> oval.draw(win)
使用图形对象 • 系统通过让对象执行它相应的函数来实现相应的功能. • 在前一个例子中,我们使用了GraphWin, Point, Circle, Oval, Line, Text 以及 Rectangle. 它们向我们展示了这些类是如何使用的.
使用图形对象 • 每一个对象都是一个类的实例,这个类描述了这个实例的特性。 • 如果我们说Augie 是一条狗, 我们实际上是在说Augie 狗这个大类中的一个特定的个体. Augie是狗这个类的一个实例。
使用图形对象 • 我们使用一个特定的操作称为构造函数(constructor)来新创建一个类的实例.<class-name>(<param1>, <param2>, …) • <class-name>是我们想要构建的实例的类的名字, 例如. Circle 或者 Point. • 参数是用来初始化这个对象用的。例如:Point 需要两个数字参数
使用图形对象 • p = Point(50, 60)Point类的构造函数需要两个参数,点的x与y坐标 . • 这些值会作为实例变量存储在对象中.
使用图形对象 • 这里只展示了最相关的实例变量(其它的还包括颜色,父窗口等等暂时隐藏)
使用图形对象 • 要让对象执行操作,我们需要给对象传递一个信息,而一个对象可以响应的所有的信息集合称作这个对象的方法(Method) . • 方法就好比对象内部的函数 • 你可以通过“点”来调用方法:<object>.<method-name>(<param1>, <param2>, …)
使用图形对象 • p.getX() 与 p.getY() 返回一个点的x与y的值. 像这种常规方法被称为访问方法(accessors),因为它们可以获取对象中的实例变量信息.
使用图形对象 • 其它的方法通过改变对象的实例变量的值来改变对象的状态. • move(dx, dy) 把对象在x方向上移动dx个单位在y方向上移动dy个单位. • Move操作擦除了老的图像,然后在新位置上绘制一个新图像. 像这种改变对象状态的方法称为修改方法(mutators).
使用图形对象 >>> circ = Circle(Point(100, 100), 30)>>> win = GraphWin()>>> circ.draw(win) • 第一行创建了一个半径30,圆点在(100,100)的圆. • 我们使用Point构造函数为这个圆的中心创建了一个点 . • 最后一行是Circle对象circ在GraphWin对象win中绘制它自己.
使用图形对象 • draw方法会使用实例变量,获取圆点、半径信息.
使用图形对象 • 两个不同的变量指向同一个对象是可以的——这时对其中一个变量的修改会直接同步影响到另一个变量 >>> leftEye = Circle(Point(80,50), 5)>>> leftEye.setFill('yellow')>>> leftEye.setOutline('red')>>> rightEye = leftEye>>> rightEye.move(20,0) • 这段代码的想法是首先创建一个左眼对象,然后把它拷贝给右眼对象,然后移动右眼对象20个单位(相当于画两只眼睛,可惜它没有成功).
使用图形对象 • 赋值语句 rightEye = leftEye 让左眼与右眼都指向了同一个circle对象! • 像这种两个变量都指向同一个对象的情形,成为别名(aliasing).
使用图形对象 • 有两种方法可以解决这个别名问题. • 我们可以绘制两个圆circles, 给两个眼睛分别画一个:>>> leftEye = Circle(Point(80, 50), 5)>>> leftEye.setFill('yellow')>>> leftEye.setOutline('red')>>> rightEye = Circle(Point(100, 50), 5)>>> rightEye.setFill('yellow')>>> rightEye.setOutline('red')
使用图形对象 • 图形库里有个更好的解决办法. 图形对象有一个拷贝方法(clone),可以拷贝该对象>>> # Correct way to create two circles, using clone>>> leftEye = Circle(Point(80, 50), 5)>>> leftEye.setFill('yellow')>>> leftEye.setOutline('red')>>> rightEye = leftEye.clone() # rightEye is an exact copy of the left>>> rightEye.move(20, 0)
数据绘制/选择坐标 win = GraphWin("Investment Growth Chart", 320, 240) win.setCoords(-1.75,-200, 11.5, 10400)
可交互的图形界面 • 在图形界面环境中,用户通常通过点击按钮、选择菜单选项、在输入框中输入文字来实现与程序的交互. • 事件驱动(Event-driven) 程序在屏幕上绘制交互元素(小插件/widgets),然后等待用户操作.
可交互的图形界面 • 当用户移动鼠标、点击鼠标或者敲打键盘是,一个事件(event)就产生了. • 事件是一个对象,它封装了刚刚发生的事件的信息 • 事件对象会被送给程序的相应部分进行处理,比如按钮事件(button event).
可交互的图形界面 • 图形操作模块隐藏了底层的窗口操作管理,只在GraphWin中提供了两个简单的方法来获取用户输入.
获取鼠标点击 • 我们可以通过调用GraphWin类中的getMouse方法来获取图形信息. • 当GraphWin中的getMouse被调用时, 程序暂停运行,然后等待用户在窗口中的某处点击鼠标. • 用户点击的地方的信息会封装成Point返回.
获取鼠标点击 • 这段代码可以打印鼠标点击的坐标:from graphics import *win = GraphWin("Click Me!")p = win.getMouse()print "You clicked (%d, %d)" % (p.getX(), p.getY()) • 对于返回的point的操作,我们可以使用访问方法例如 getX以及 getY或者其他的方法.
获取鼠标点击 # triangle.pyw # 用可交互的图形编程来画一个三角形 from graphics import * def main(): win = GraphWin("画一个三角形") win.setCoords(0.0, 0.0, 10.0, 10.0) message = Text(Point(5, 0.5), "请点三个点") message.draw(win) # 获取并绘制三角形的三个顶点 p1 = win.getMouse() p1.draw(win) p2 = win.getMouse() p2.draw(win) p3 = win.getMouse() p3.draw(win)
获取鼠标点击 # 使用多边形对象来绘制三角形 triangle = Polygon(p1,p2,p3) triangle.setFill("peachpuff") triangle.setOutline("cyan") triangle.draw(win) # 等待再一次点击推出程序 message.setText("随便点击推出程序.") win.getMouse() main()
获取鼠标点击 • 注意: • 当你在windows环境下编程时, 如果你使用 .pyw后缀,双击运行你的python程序时,Python的shell窗口不会显示出来. • 没有三角形类,所以我使用了更一般的多边形类,这个类可以把任意多的点连接成一个封闭图形.
获取鼠标点击 • 一旦你获取了三个点, 创建一个三角形就很容易了:triangle = Polygon(p1, p2, p3) • 在程序的开始处创建并绘制一个文本对象.message = Text(Point(5,0.5), “Click on three points”)message.draw(win) • 要改变提示,只要修改要展示的文字即可message.setText(“Click anywhere to quit.”)
处理文字输入 • 这个三角形程序的输入完全靠鼠标点击. 这里还有一个 Entry对象可以获取键盘输入. • Entry对象能在屏幕上绘制一个文本框,可以包含文本. 这个对象同样也有setText与getText方法,不过它还能编辑输入.
处理文字输入 # convert_gui.pyw # 使用简单的图形界面 # 实现的摄氏度转华氏度的程序. from graphics import * def main(): win = GraphWin("Celsius Converter", 300, 200) win.setCoords(0.0, 0.0, 3.0, 4.0) # 绘制界面 Text(Point(1,3), " Celsius Temperature:").draw(win) Text(Point(1,1), "Fahrenheit Temperature:").draw(win) input = Entry(Point(2,3), 5) input.setText("0.0") input.draw(win) output = Text(Point(2,1),"") output.draw(win) button = Text(Point(1.5,2.0),"Convert It") button.draw(win) Rectangle(Point(1,1.5), Point(2,2.5)).draw(win)