课程 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 说明

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()

✅ 第四步:测试与完善

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

4.2 逐步求精编程思想

🧠 逐步求精(Stepwise Refinement)

逐步求精是一种将复杂问题分解为若干简单步骤、逐步细化实现的编程思想。

📝 核心步骤

  1. 问题分解:将复杂问题分解为多个简单子问题
  2. 逐步细化:对每个子问题进一步细化
  3. 分步实现:逐个实现每个子问题
  4. 测试完善:测试每个步骤,逐步完善

🎯 应用场景

5. 图形编程总结

✅ 图形编程要点总结

⚠️ 注意事项

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

基础练习:
1. 用graphics.py画一个彩色的房子。

2. 实现点击画布时在点击处画一个小圆点。

图形绘制练习:
3. 绘制一个简单的国旗(如中国国旗、美国国旗等)。

4. 创建一个程序,绘制各种几何图形(三角形、菱形、五角星等)。

5. 实现一个简单的画板程序,支持绘制不同颜色的线条。

交互练习:
6. 创建一个程序,用键盘控制一个图形在画布上移动。

7. 实现一个简单的贪吃蛇游戏,用方向键控制蛇的移动。

8. 创建一个程序,点击按钮时改变画布上图形的颜色。

动画练习:
9. 实现一个弹跳球动画,球在画布边界反弹。

10. 创建一个程序,让多个图形同时移动形成动画效果。

综合应用:
11. 设计并实现一个简单的游戏(如打砖块、飞机大战等)。

12. 创建一个数据可视化程序,用图形展示简单的数据。

创意练习:
13. 自由创作一个有趣的图形程序,展示你的创意。

14. 尝试使用不同的颜色搭配和图形组合,创造美观的视觉效果。

提交要求:
- 所有代码必须包含详细注释 - 遵循Python编码规范 - 提供程序运行截图 - 说明程序的设计思路和实现步骤 - 对于复杂的程序,请说明使用了哪些graphics.py的API