课程 7:图形编程

课程目录

图形编程简介:
图形编程(Graphical Programming)是指通过编写代码,创建和操作图形界面(GUI, Graphical User Interface)或图形元素(如点、线、面、图像等),让程序能够以可视化的方式与用户交互或展示信息。本课程将学习使用graphics.py库进行图形编程,培养面向对象和事件驱动编程思想。

1. 图形编程概述

1.1 什么是图形编程

图形编程概念

图形编程(Graphical Programming)是指通过编写代码,创建和操作图形界面(GUI, Graphical User Interface)或图形元素(如点、线、面、图像等),让程序能够以可视化的方式与用户交互或展示信息。

主要应用领域

1.2 Python中的图形编程

Python图形库

为什么学习图形编程

1.3 什么是API

API概念

API(Application Programming Interface,应用程序编程接口)是指一组预先定义好的函数、类、方法或协议,供开发者调用,用来实现特定功能或与某个系统、库、服务进行交互。

API的比喻

API就像"菜单":你去餐厅点菜,菜单上列出了你可以点的菜(功能),但你不需要关心后厨怎么做(内部实现)。你只需要按照菜单(API)上的说明点菜(调用函数),就能得到想要的结果。

API在编程中的作用

2. graphics.py 常用 API 说明

graphics.py 库简介

graphics.py 是由斯坦福大学计算机科学系开发的Python图形编程库,专门为计算机科学教育而设计。它基于Python的tkinter库构建,但提供了更加简洁和直观的API接口。

设计理念

安装与使用

# 下载graphics.py文件
# 将graphics.py文件放在项目目录中

# 导入使用
from graphics import Canvas

# 创建画布
canvas = Canvas(width=400, height=300, title="我的图形程序")
canvas.mainloop()

2.1 画布相关

画布创建和管理

# 创建画布
Canvas(width=500, height=600, title='Canvas')  # 创建一个画布窗口,可指定宽度、高度和窗口标题

# 获取画布信息
canvas.get_width()   # 获取画布宽度(像素)
canvas.get_height()  # 获取画布高度(像素)

# 设置画布属性
canvas.set_canvas_background_fill(color)  # 设置画布背景色

2.2 图形对象创建

基本图形创建

# 创建矩形
canvas.create_rectangle(x1, y1, x2, y2, color='black')  # 左上角(x1,y1),右下角(x2,y2)

# 创建椭圆
canvas.create_oval(x1, y1, x2, y2, color='black')  # 外接矩形为(x1,y1)-(x2,y2)

# 创建线段
canvas.create_line(x1, y1, x2, y2, color='black', width=1)  # 从(x1,y1)到(x2,y2)

# 创建多边形
canvas.create_polygon(points, outline='black', fill='color', width=1)  # points为点坐标列表

# 创建文本
canvas.create_text(x, y, text, font='Arial', font_size=12, color='black', anchor='nw')

# 创建图片
canvas.create_image(x, y, file_path, width=None, height=None)  # 加载并显示图片

2.3 图形对象操作

对象移动和定位

# 相对移动
canvas.move(obj, dx, dy)  # 将对象obj相对当前位置移动(dx,dy)

# 绝对定位
canvas.moveto(obj, x, y)  # 将对象obj移动到新位置(x,y)

move与moveto的区别

方法 作用 参数含义 适用场景
move 相对移动 dx, dy 连续、增量式移动
moveto 绝对定位 x, y 跳转到指定位置

对象属性修改

# 删除对象
canvas.delete(obj)  # 删除对象obj

# 设置颜色
canvas.set_fill_color(obj, color)      # 设置对象填充色
canvas.set_outline_color(obj, color)   # 设置对象轮廓色

# 设置文本属性
canvas.set_font(obj, font, size)       # 设置文本对象字体和字号
canvas.set_text(obj, text)             # 修改文本内容

# 层级调整
canvas.raise_to_front(obj)  # 将对象置于最前
canvas.lower_to_back(obj)   # 将对象置于最后

2.4 获取对象信息

对象信息获取

# 获取对象尺寸
canvas.get_obj_width(obj)   # 获取对象宽度
canvas.get_obj_height(obj)  # 获取对象高度

# 获取对象位置
canvas.get_left_x(obj)      # 获取对象最左侧x坐标
canvas.get_top_y(obj)       # 获取对象最顶部y坐标

2.5 事件处理

鼠标和键盘事件

# 鼠标事件
canvas.on_mouse_pressed = func  # 设置鼠标按下事件回调

# 键盘事件
canvas.on_key_pressed = func    # 设置键盘按下事件回调

# 等待点击
canvas.wait_for_click()         # 阻塞,直到用户点击画布

键盘事件说明

on_key_pressed回调的参数是按下的键名(如"Left", "a", "space"等)。你可以用方向键、字母键、数字键、空格等任意键来控制图形。

常用按键名对照表

方向键 (Arrow Keys)
  • "Left" - 左箭头键
  • "Right" - 右箭头键
  • "Up" - 上箭头键
  • "Down" - 下箭头键
字母键 (Letter Keys)
  • "a" - 字母A(小写)
  • "A" - 字母A(大写,需要Shift)
  • "w" - 字母W(小写)
  • "s" - 字母S(小写)
  • "d" - 字母D(小写)
数字键 (Number Keys)
  • "1" - 数字1
  • "2" - 数字2
  • "3" - 数字3
  • "0" - 数字0
功能键 (Function Keys)
  • "space" - 空格键
  • "Enter" - 回车键
  • "Escape" - ESC键
  • "Tab" - Tab键
  • "BackSpace" - 退格键
修饰键 (Modifier Keys)
  • "Shift" - Shift键
  • "Control" - Ctrl键
  • "Alt" - Alt键

按键名使用技巧

2.6 交互控件

控件创建

# 创建按钮
canvas.create_button(title, location)  # 添加按钮

# 创建文本框
canvas.create_text_field(label, location)  # 添加文本框
canvas.get_text_field_text(label)          # 获取文本框内容

2.7 画布管理与常用指令

画布管理基础

# 清空画布
canvas.clear()  # 清空画布所有对象

# 启动事件循环
canvas.mainloop()  # 启动事件循环,显示窗口(程序结尾必加)

# 设置画布标题
canvas.set_canvas_title("我的图形程序")  # 设置窗口标题

# 设置画布大小
canvas.set_canvas_size(width, height)  # 动态调整画布大小

时间控制与动画

# 暂停执行
canvas.after(milliseconds)  # 暂停指定毫秒数(非阻塞)

# 定时执行
canvas.after(milliseconds, function)  # 延迟执行指定函数

# 重复执行
def repeat_action():
    # 执行动画逻辑
    canvas.after(50, repeat_action)  # 每50毫秒重复执行

# 强制更新画布
canvas.update()  # 强制刷新画布显示(重要:确保动画可见)

画布状态管理

# 获取画布信息
canvas.get_width()   # 获取画布宽度
canvas.get_height()  # 获取画布高度

# 设置画布属性
canvas.set_canvas_background_fill(color)  # 设置背景色

# 画布可见性控制
canvas.set_canvas_visible(True/False)  # 显示/隐藏画布

# 画布焦点控制
canvas.set_canvas_focus()  # 设置画布获得焦点

对象查找与管理

# 查找对象
canvas.find_object_at(x, y)  # 查找指定坐标的对象

# 获取所有对象
canvas.get_all_objects()  # 获取画布上所有对象的列表

# 对象存在性检查
canvas.object_exists(obj)  # 检查对象是否仍然存在

# 批量操作
for obj in canvas.get_all_objects():
    canvas.delete(obj)  # 删除所有对象

性能优化指令

# 暂停重绘(批量操作时使用)
canvas.suspend_updates()  # 暂停画布更新
# ... 执行多个操作 ...
canvas.resume_updates()   # 恢复画布更新

# 设置动画帧率
FRAME_RATE = 60  # 60帧/秒
FRAME_DELAY = 1000 // FRAME_RATE  # 计算帧延迟

# 非阻塞动画循环
def animate():
    # 更新对象位置
    canvas.move(ball, dx, dy)
    canvas.update()  # 确保动画可见
    canvas.after(FRAME_DELAY, animate)  # 安排下一帧

重要注意事项

3. 典型绘图示例

3.1 基本图形绘制

绘制矩形

# 画一个红色矩形
from graphics import Canvas
canvas = Canvas(width=400, height=300)
rect = canvas.create_rectangle(50, 50, 200, 150, color='red')
canvas.mainloop()

绘制椭圆

# 画一个蓝色椭圆
from graphics import Canvas
canvas = Canvas(width=400, height=300)
oval = canvas.create_oval(100, 100, 300, 200, color='blue')
canvas.mainloop()

显示文本

# 显示文本
from graphics import Canvas
canvas = Canvas(width=400, height=300)
text = canvas.create_text(200, 150, 'Hello, world!', font_size=20, color='green')
canvas.mainloop()

加载图片

# 加载图片(需安装 pillow)
from graphics import Canvas
canvas = Canvas(width=400, height=300)
img = canvas.create_image(100, 100, 'cat.png', width=100, height=100)
canvas.mainloop()

3.2 事件处理示例

响应鼠标点击事件

# 响应鼠标点击事件
from graphics import Canvas
canvas = Canvas(width=400, height=300)

def on_click(x, y):
    canvas.create_oval(x-10, y-10, x+10, y+10, color='orange')

canvas.on_mouse_pressed = on_click
canvas.mainloop()

说明:on_mouse_pressed是鼠标点击事件的回调函数。你可以自定义一个函数(如on_click),参数为点击的x, y坐标,然后将其赋值给canvas.on_mouse_pressed。当用户点击画布时,该函数会被自动调用。

用键盘控制小球移动

# 用键盘控制小球移动(支持方向键和WASD)
from graphics import Canvas
canvas = Canvas(width=400, height=400)
ball = canvas.create_oval(180, 180, 220, 220, color='blue')

def on_key(key):
    dx, dy = 0, 0
    if key == "Left" or key == "a":
        dx = -10
    elif key == "Right" or key == "d":
        dx = 10
    elif key == "Up" or key == "w":
        dy = -10
    elif key == "Down" or key == "s":
        dy = 10
    canvas.move(ball, dx, dy)

canvas.on_key_pressed = on_key
canvas.mainloop()

提示:你可以尝试用不同的键名控制不同的图形,实现丰富的交互效果!

4. 教学演示案例:绘制彩色小房子

4.1 逐步求精:分步绘制彩色小房子

彩色小房子示例

效果示例:

第一步:明确目标

目标:在画布上绘制一个带有门、窗、屋顶的彩色小房子。

第二步:分解主要部分

  1. 画房子主体(矩形)
  2. 画屋顶(三角形)
  3. 画门(小矩形)
  4. 画窗户(两个小矩形)
  5. 画门把手(小圆)

第三步:伪代码与分步实现

# 伪代码
main():
    画房子主体
    画屋顶
    画门
    画窗户
    画门把手

# 分步实现
from graphics import Canvas
canvas = Canvas(width=400, height=350)

# 1. 画房子主体
body = canvas.create_rectangle(100, 180, 300, 320, color='burlywood')

# 2. 画屋顶
roof = canvas.create_polygon([100, 180, 200, 100, 300, 180], fill='sienna', outline='black')

# 3. 画门
door = canvas.create_rectangle(170, 250, 230, 320, color='saddlebrown')

# 4. 画窗户
window1 = canvas.create_rectangle(120, 200, 160, 240, color='skyblue')
window2 = canvas.create_rectangle(240, 200, 280, 240, color='skyblue')

# 5. 画门把手
knob = canvas.create_oval(220, 285, 228, 293, color='gold')

canvas.mainloop()

第四步:测试与完善

建议:你在写更复杂的图形或交互程序时,也采用这种分解-细化-实现-完善的思路!

5. 图形编程总结

图形编程要点总结

注意事项

温馨提示:图形编程让编程变得更有趣和直观,多尝试组合不同的API,完成有趣的图形和交互效果。