1.创建和显示窗口

1. cv2.namedWindow(winname, flags)
- 作用 :提前创建窗口,自定义窗口属性;不调用此函数直接
imshow会生成默认不可缩放窗口 - 参数:
winname:窗口唯一名称,后续操作窗口都靠名称匹配flags窗口模式:cv2.WINDOW_NORMAL:窗口可拖拽缩放cv2.WINDOW_AUTOSIZE:默认,自适应图像大小,不能手动拉伸cv2.WINDOW_FREERATIO:自由比例缩放,不受原图比例限制
2. cv2.resizeWindow(winname, width, height)
- 作用:强制设置窗口像素宽高,仅对
WINDOW_NORMAL模式窗口生效 - 注意:数值是窗口尺寸,不是图片分辨率
3. cv2.imshow(winname, mat)
- 作用:在指定窗口渲染图像
mat=0:代表创建一张全黑空白单通道画布;正常使用时传入读取的图片矩阵,如cv2.imread("test.jpg")
4. cv2.waitKey(delay)
delay:等待毫秒数,0代表无限等待按键;1持续刷新监听& 0xFF:兼容 64 位系统,只取按键 ASCII 低 8 位,避免数值异常- 常用按键 ASCII:
q=113、esc=27
5. cv2.destroyWindow(winname) / cv2.destroyAllWindows()
destroyWindow:关闭指定名称窗口destroyAllWindows():一次性关闭所有 OpenCV 窗口(推荐收尾使用)
cv2.waitKey() 返回的是数字 ASCII 码,不是字符串
key == 'q' 永远不成立,'q' 的 ASCII 码是 113 ,应该判断数字 113 或 ord('q')
2.图片的读取

python运行
image = cv2.imread(filename, flags=cv2.IMREAD_COLOR)
-
参数 1 filename 文件路径
- 代码中使用原始字符串
r"路径",避免 Windows 反斜杠\转义报错,推荐写法; - 支持绝对路径(如截图完整 C 盘路径)、相对路径;
- ⚠️常见坑:路径包含中文 / 空格、文件不存在、后缀写错,都会返回
None,窗口显示空白。
- 代码中使用原始字符串
-
参数 2 flags 读取模式(可选)
表格
参数 效果 cv2.IMREAD_COLOR默认彩色图,丢弃透明度通道 cv2.IMREAD_GRAYSCALE以灰度单通道读取 cv2.IMREAD_UNCHANGED完整读取,保留透明 Alpha 通道
3.图片的保存

函数作用
将内存中的图像矩阵写入本地磁盘,保存为图片文件。
语法
python
运行
cv2.imwrite(filename, img, params=None)
- filename:保存路径 + 文件名(代码:
../data/1.png)../代表上级目录 ,表示在代码文件的上一层新建data文件夹,输出1.png;- 支持相对路径、绝对路径;支持格式:png/jpg/bmp/tiff 等;
- ⚠️关键坑:路径中不存在 data 文件夹会保存失败,不会自动创建目录。
- img:要保存的图像矩阵 必须是
cv2.imread()读取得到的 numpy 数组,不能传 None。 - params(可选) :图片质量压缩参数
- JPG:
[cv2.IMWRITE_JPEG_QUALITY, 0~100]数值越大画质越高 - PNG:
[cv2.IMWRITE_PNG_COMPRESSION, 0~9]数值越大压缩率越高
- JPG:
返回值
布尔值:True保存成功;False保存失败(目录不存在、矩阵为空、格式不支持)。v
4.视频的采集

语法与参数
python
运行
cap = cv2.VideoCapture(source)
- source=0(代码中使用) 代表读取本机默认摄像头设备;
- 外接多摄像头可填
1、2...切换设备; - 传入视频文件路径字符串(如
test.mp4)可读取本地视频; - 传入网络 RTSP/RTMP 流地址可读取监控视频流。
- 外接多摄像头可填
- 返回值
cap:视频捕获对象,用于读取帧、释放设备、获取视频参数。
关键判断方法
cap.isOpened():返回布尔值,判断摄像头 / 视频是否成功打开,防止设备占用、找不到设备报错。
ret, frame = cap.read()
- 作用:读取视频下一帧画面
- 返回两个参数:
ret:布尔值,True正常读到帧;False视频结束 / 摄像头断开 / 读取失败frame:numpy 图像矩阵(BGR 三通道),无画面时为None
- 循环核心逻辑,视频 / 摄像头必备
5.视频文件的读取

6.视频的录制以及保存


要设计好编码方式以及分辨率大小要和设备相适应,不然会损坏文件格式,导致文件不能读取
一、红框 1:cv2.VideoWriter_fourcc(*'mp4v')
作用
生成视频编码格式的 4 字节标识符(FourCC 编码),用于指定输出视频的压缩标准。
参数说明
*'mp4v':解包字符串,代表 MPEG-4 编码,配套后缀.mp4,兼容性最强;- 其他常用编码:
*'XVID'→ 输出.avi*'avc1'→ H.264 高清 mp4
返回值
数字编码 ID,作为VideoWriter的入参。
二、红框 2:获取摄像头分辨率 + cv2.VideoWriter()
1. 分辨率读取 API cap.get()
python
运行
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cap.get(属性ID):读取视频捕获设备参数cv2.CAP_PROP_FRAME_WIDTH/HEIGHT:获取摄像头原生宽高- 必须转
int,返回值默认浮点型
2. cv2.VideoWriter(保存路径, fourcc, fps, (width,height)) 视频写入器构造函数
参数逐项解析:
'../data/4.mp4':输出视频相对路径;data 文件夹不存在会录制失败fourcc:第一步生成的编码标识符20.0:录制帧率 20fps,要和摄像头实际帧率匹配,画面才不会变速(w, h):输出视频分辨率,必须和写入的 frame 尺寸完全一致,否则保存黑屏
返回值
vw视频写入对象,所有保存操作依赖该对象。
三、红框 3:vw.write(frame)
作用
将单帧图像矩阵写入视频文件流,循环执行即可拼接成完整视频。
要求
传入的frame必须是 BGR 三通道图像,尺寸严格等于VideoWriter初始化设置的(w,h)。
四、红框 4:vw.release()
核心作用
关闭视频文件流,完成文件封装、写入磁盘缓存; ⚠️ 必写:不调用该函数,视频文件会损坏、无法打开。

7.设置鼠标监听事件


一、红框 1:鼠标回调函数 def mouse_callback(event, x, y, flags, userdata)
函数固定参数(5 个参数顺序不可改变)
-
event:鼠标事件类型(整数常量)表格
常量 含义 cv2.EVENT_LBUTTONDOWN左键按下 cv2.EVENT_RBUTTONDOWN右键按下 cv2.EVENT_MBUTTONDOWN中键按下 cv2.EVENT_MOUSEMOVE鼠标移动 cv2.EVENT_LBUTTONUP左键松开 cv2.EVENT_MOUSEWHEEL滚轮滚动 -
x, y:鼠标当前在窗口图像上的像素坐标 -
flags:按键标记,判断是否按住 Ctrl/Shift/ 鼠标左右键等组合操作 -
userdata:setMouseCallback传入的自定义额外参数,无需求可传None
代码作用
触发鼠标动作时自动执行此函数,示例中直接打印所有参数查看鼠标状态。
二、红框 2:绑定鼠标回调 cv2.setMouseCallback(windowName, mouse_callback, param=None)
参数解析
windowName:要监听鼠标的窗口名称,必须和namedWindow创建的窗口名完全一致(图中mouse)mouse_callback:自定义鼠标回调函数名(无需加括号,只传函数引用)param(可选):传给回调函数第 5 个参数userdata的自定义数据
核心功能
将自定义鼠标处理函数和指定窗口绑定,窗口内所有鼠标动作都会自动触发回调函数。
三、红框 3:创建空白画布 img = np.zeros((600, 800, 3), dtype=np.uint8)
依赖 numpy 库生成黑色图像矩阵,作为鼠标操作的背景面板:
(600, 800, 3):形状(高度h, 宽度w, 通道数),600 行 800 列 3 通道彩色图np.uint8:像素数据类型,取值 0~255,OpenCV 图像标准类型np.zeros:全部像素初始化为 0,即纯黑色画布
8.创建trackbar函数


一、第一组红框:cv2.createTrackbar() 创建滑动条
函数语法
python
运行
cv2.createTrackbar(trackbarName, windowName, value, count, onChange)
参数拆解
trackbarName:滑动条名称(图中R/G/B,用于后续读取数值)windowName:绑定到的窗口名称,必须和namedWindow窗口名完全一致(图中trackbar)value:滑动条初始默认值(代码截图省略,一般填 0)count:滑动条最大值,调色场景固定 255(像素 0~255)onChange:滑动拖动时触发的回调函数,代码中传入callback空函数pass
作用
在指定窗口顶部生成可视化拖动滑块,用于动态调节数值。
二、第二组红框:img = np.zeros((512, 512, 3), np.uint8) 创建调色画布
基于 NumPy 生成彩色黑色底板:
(512, 512, 3):(高度,宽度,通道数),512×512 三通道彩色图np.uint8:像素标准数据类型,取值 0~255- 初始全 0,默认纯黑色,后续用滑动条 RGB 数值覆盖底色
三、第三组红框:cv2.getTrackbarPos() 读取滑块数值
函数语法
python
运行
val = cv2.getTrackbarPos(trackbarname, winname)
参数拆解
trackbarname:滑动条名称,和createTrackbar第一个参数对应(R/G/B)winname:窗口名称
返回值
当前滑块拖动到的整数数值(0~255)
代码逻辑
python
运行
r = cv2.getTrackbarPos('R','trackbar')
g = cv2.getTrackbarPos('G','trackbar')
b = cv2.getTrackbarPos('B','trackbar')
实时获取红、绿、蓝三个通道的滑块值。
四、第四组红框:画布赋值与窗口渲染
python
运行
img[:] = np.array([b, g, r])
cv2.imshow('trackbar', img)
img[:] = np.array([b,g,r])OpenCV 图像通道顺序是BGR,所以赋值顺序为蓝、绿、红;整幅画布所有像素统一设置为当前滑块组合的颜色。cv2.imshow:循环刷新窗口,实时展示调色后的画布。

9.颜色空间转换
import cv2
# 滑动条必填空回调
def callback(val):
pass
# 1. 创建窗口+读取图片
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = cv2.imread('../data/1.png')
# 判空,防止图片找不到报错
if img is None:
print("图片文件不存在!")
exit()
# 2. 定义所有颜色转换规则
colorspaces = [
cv2.COLOR_BGR2RGBA,
cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY,
cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV
]
# 3. 创建滑动条 范围0~4
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)
# 4. 循环切换颜色空间
while True:
index = cv2.getTrackbarPos('curcolor', 'color')
# 颜色转换核心
cvt_img = cv2.cvtColor(img, colorspaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if key & 0xFF == ord('a'):
break
cv2.destroyAllWindows()
二、颜色空间转换常量数组
python
运行
# 定义列表,存放5种BGR转其他空间的转换标识
colorspaces = [
cv2.COLOR_BGR2RGBA, # 0:BGR → RGBA(带透明通道4通道)
cv2.COLOR_BGR2BGRA, # 1:BGR → BGRA(自带透明通道4通道)
cv2.COLOR_BGR2GRAY, # 2:BGR → 灰度单通道
cv2.COLOR_BGR2HSV, # 3:BGR → HSV(色相饱和度,图像分割常用)
cv2.COLOR_BGR2YUV # 4:BGR → YUV(视频、摄像头图像处理)
]
列表下标 0、1、2、3、4 对应 5 种转换方式,后面用滑动条数值选取。
三、创建滑动条 Trackbar
python
运行
# 创建名为curcolor的滑块,绑定color窗口
# 初始值0,最大值4,拖动触发callback函数
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)
- 最大值设为 4,刚好匹配数组
colorspaces长度(下标 0~4),拖动滑块取值对应转换方式。 callback:必须提前定义空回调函数,示例最简写法:def callback(val): pass
四、循环核心逻辑(滑动条联动颜色转换)
python
运行
while True:
# 1. 获取当前滑块数值 0~4
index = cv2.getTrackbarPos('curcolor', 'color')
# 2. 核心API:cv2.cvtColor 颜色空间转换
cvt_img = cv2.cvtColor(img, colorspaces[index])
# 3. 渲染转换后的图像
cv2.imshow('color', cvt_img)
# 等待10ms按键输入
key = cv2.waitKey(10)
print(key)
# 按下a键退出循环
if key & 0xFF == ord('a'):
break
核心 API:cv2.cvtColor(src, code)
- src :原始图像(这里是读取的 BGR 原图
img) - code :转换编码(列表
colorspaces里的常量) - 返回值:转换后新图像矩阵
cvt_img
滑动条联动逻辑
- 滑块拖到 0 →
colorspaces[0]→COLOR_BGR2RGBA - 滑块拖到 2 →
colorspaces[2]→COLOR_BGR2GRAY灰度图 - 滑块拖到 3 →
colorspaces[3]→ HSV 颜色空间
各个颜色空间作用通俗解释
表格
| 转换常量 | 输出通道 | 用途 |
|---|---|---|
| COLOR_BGR2RGBA | 4 通道 (R+G+B + 透明) | 前端图片、透明贴图 |
| COLOR_BGR2BGRA | 4 通道 (B+G+R + 透明) | OpenCV 原生透明图 |
| COLOR_BGR2GRAY | 单通道灰度 | 轮廓检测、人脸识别、简化计算 |
| COLOR_BGR2HSV | 3 通道 (H 色相,S 饱和度,V 明度) | 颜色筛选、目标跟踪(提取红色 / 蓝色物体) |
| COLOR_BGR2YUV | 3 通道 (Y 亮度,U/V 色度) | 摄像头、视频流处理,降低亮度干扰 |
效果如图所示

10.深拷贝与浅拷贝

1. 浅拷贝(你的代码 image2 = image)
python
运行
image2 = image
- 只复制栈内存的引用指针,不会新开像素存储内存;
image和image2指向同一块像素堆内存;- 任意一个变量修改像素,另一个同步变化;
- 开销极小,只复制表头信息,不复制图像像素。
流程图:
plaintext
image 指针 ──┐
├─→ 同一份像素数据内存
image2指针 ──┘
2. 深拷贝(完全独立新图像)
使用 .copy() 方法开辟全新像素内存:
python
运行
image2 = image.copy()
- 复制栈表头信息 + 完整复制堆里全部像素数据;
image和image2是两块完全独立内存;- 修改任意一张图,另一张完全不受影响;
- 开销更大,大图复制会占用双倍内存。
11.通道的分割与合并

cv2.line 官方函数原型
python
运行
cv2.line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
逐个参数拆解:
1. img
- 类型:
numpy.ndarray(OpenCV 图像数组) - 含义:要绘制线条的目标图像画布,绘图会直接修改这张图(浅拷贝原地修改)
- 你的代码:
img = np.zeros((512,512,3), np.uint8)黑色画布作为绘图载体
2. pt1
- 类型:元组
(x1, y1) - 含义:直线起点坐标
- 图像坐标系规则:
- 图片左上角是原点
(0,0) - x 轴:水平向右(列)
- y 轴:垂直向下(行)
- 图片左上角是原点
- 你的代码:
(100, 100)→ 起点:横向 100,纵向 100
3. pt2
- 类型:元组
(x2, y2) - 含义:直线终点坐标
- 你的代码:
(200, 200)→ 终点:横向 200,纵向 200
4. color
- 类型:元组
(B, G, R) - 重点:OpenCV 颜色通道顺序是 BGR,不是 RGB!
- 你的代码:
(0,0,255)- B=0,G=0,R=255 → 纯红色线条
- 举例:
(255,0,0)= 蓝色,(0,255,0)= 绿色,(255,255,255)= 白色
5. thickness
- 类型:整数
- 含义:线条粗细像素值
- 你的代码:
5→ 线条宽度 5 个像素 - 补充:如果填负数,不会变成空心,
line()仅支持实线粗细,填充图形(矩形 / 圆)才支持 - 1 填充。
6. lineType(你代码里传的 4)
线条渲染类型,抗锯齿 / 普通直线模式:
表格
| 参数值 | 常量名 | 效果说明 |
|---|---|---|
| 4 | cv2.LINE_4 |
4 连通直线,锯齿明显,速度快 |
| 8 | cv2.LINE_8 |
8 连通直线,默认值,锯齿轻微 |
| 16 | cv2.LINE_AA |
抗锯齿直线,线条最平滑,计算稍慢 |
你代码里写 4 = cv2.LINE_4,使用 4 邻域插值绘制直线。
7. shift(可选,你没传)
坐标小数精度缩放,默认 0;用于亚像素高精度绘图,日常开发几乎不用。
12.画椭圆


cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift)
1. img
- 含义:画布图像,
numpy.ndarray数组 - 作用:椭圆 / 椭圆弧会直接绘制在这张图上,原地修改。
2. 中心点 center
- 格式:元组
(x, y) - 含义:椭圆几何中心的像素坐标,图像坐标系原点在左上角,x 向右、y 向下。
3. 长宽的一半 axes
- 格式:元组
(半长轴, 半短轴) - 关键点:是轴长的一半(半径),不是完整直径
- axes=(100,50) → 椭圆完整宽度 200,高度 100。
4. 角度 angle
单位:度(°)
- 含义:椭圆整体绕中心点逆时针旋转的角度。
- 示例:angle=30 → 椭圆本体倾斜 30 度。
5. 从哪个角度开始 startAngle
6. 到哪个角度结束 endAngle
单位:度(°),用来控制绘制一段椭圆弧,而非完整椭圆
- 基准 0°:旋转后椭圆的右侧水平端点(x 轴正方向)
- 绘制方向:从 startAngle 逆时针走到 endAngle
startAngle=0, endAngle=360:绘制完整闭合椭圆startAngle=0, endAngle=180:只画上半椭圆弧
后置可选参数(图片未标出)
color:绘制颜色,单通道灰度填数值,彩色图填(B,G,R)thickness:轮廓线宽度- 正数:空心轮廓;
-1/cv2.FILLED:填充椭圆
- 正数:空心轮廓;
lineType:线条抗锯齿类型(默认 8 邻域)shift:坐标小数精度,日常绘图填 0 即可
13.绘制多边形

函数原型(Python)
python
运行
cv2.polylines(img, pts, isClosed, color, thickness, lineType, shift)
图片中标注了前 4 个核心参数,后面为可选绘图参数。
参数逐句对应解析
1. img
画布图像(numpy 数组),绘制的折线 / 多边形会直接修改该图像。
2. pts 点集
- 格式要求:三维数组
[[[x1,y1],[x2,y2],[x3,y3]]],支持同时绘制多个多边形(多组点嵌套) - 含义:按顺序连接的顶点坐标列表,绘图顺序严格按照数组内点的先后顺序连线。
3. isClosed 是否闭环
True:自动把最后一个顶点和第一个顶点相连,形成闭合多边形False:仅按顺序连接顶点,只绘制开放折线,首尾不相连
4. color 颜色
彩色图像传入 (B, G, R) 元组;灰度图传入单通道数值。
末尾可选参数(... 省略部分)
thickness:线条宽度,只能为正数 ,该函数无法填充图形(填充多边形使用cv2.fillPoly())lineType:线条渲染类型,默认 8 邻域,cv2.LINE_AA开启抗锯齿shift:坐标小数精度,常规绘图填 0 即可
14.绘制文本

完整函数原型(Python)
python
运行
cv2.putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)
图片中标注了前 5 个核心参数,剩余为可选参数。
参数逐段对应解析
1. img
画布图像(numpy 数组),文字会直接绘制在该图像上,原地修改。
2. text 字符串
需要绘制的文字内容; ⚠️ 限制:OpenCV 原生仅支持英文、数字、符号,直接传入中文会乱码,中文需借助 PIL 或加载自定义字体实现。
3. org 启始点
坐标元组 (x, y); 坐标系规则:默认该点是文字左下角(图像原点左上角,x 向右、y 向下)。
4. fontFace 字体
OpenCV 内置字体常量,常用值:
cv2.FONT_HERSHEY_SIMPLEX:常规无衬线字体cv2.FONT_HERSHEY_PLAIN:小号细字体cv2.FONT_HERSHEY_DUPLEX:加粗字体cv2.FONT_HERSHEY_SCRIPT_SIMPLEX:手写花体
5. fontScale 字号
字体缩放系数,浮点数;
1.0= 默认标准大小>1放大文字,<1缩小文字
图片省略的可选参数
color:文字颜色,彩色图传(B,G,R),灰度图传单数值thickness:文字线条粗细,正数;填-1无填充效果lineType:线条抗锯齿,推荐cv2.LINE_AA消除锯齿bottomLeftOrigin:布尔值,默认False;设为True时,org变为文字左上角基准点
15.综合案例
import math
import cv2
import numpy as np
'''
基本功能:
1.按住l键,可以画线
2.按住r键盘,可以画矩形
3.按下c键,可以画圆
'''
curshape = 0
startpos = (0,0)
#创建面板
cv2.namedWindow('drawshape', cv2.WINDOW_NORMAL)
#显示窗口和背景
img = np.zeros((600, 800, 3), dtype=np.uint8)
#设置回调函数
def mouse_callback(event, x, y, flags, userdata):
global startpos, curshape, img
if event == cv2.EVENT_LBUTTONDOWN:
startpos = (x,y)
elif event == cv2.EVENT_LBUTTONUP:
if curshape ==0:
cv2.line(img,startpos,(x,y),(0,0,255))
elif curshape ==1:
cv2.rectangle(img,startpos,(x,y),(0,0,255))
elif curshape ==2:
a=x-startpos[0]
b=y-startpos[1]
r=int(math.sqrt(a**2+b**2))
cv2.circle(img,startpos,r,(0,0,255))
# print(event,x,y,flags,userdata)
# 设置鼠标回调函数
cv2.setMouseCallback('drawshape', mouse_callback)
while True:
cv2.imshow('drawshape',img)
key=cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('l'):
curshape = 0
elif key == ord('r'):
curshape = 1
elif key == ord('c'):
curshape = 2
cv2.destroyAllWindows()

1. 为什么只执行一次就永久监听?
这个函数的作用是注册绑定:
- 你告诉 OpenCV:名为
drawshape的窗口,后续所有鼠标动作,统一交给mouse_callback函数处理; - 注册完成后,OpenCV 内部会单独维护一套鼠标消息监听机制,和你的
while主循环完全分开; - 只要窗口不关闭,鼠标事件会持续自动触发回调,不需要重复注册。
如果错误放进 while 循环会发生什么?
python
运行
# 错误写法,千万不要这么写
while True:
cv2.setMouseCallback('drawshape', mouse_callback)
cv2.imshow(...)
每 1ms 就重复绑定一次回调,造成:
- 资源冗余,程序卡顿;
- 多次重复绑定,鼠标一次动作会多次执行绘图逻辑;
- 无任何收益,纯浪费性能。
2. 两种监听的核心区别(帮你巩固理解)
鼠标监听(setMouseCallback)
- 模式:事件驱动、被动监听
- 执行时机:程序启动只调用 1 次注册;鼠标操作时系统自动调用回调
- 位置:写在
while True循环外部
键盘监听(cv2.waitKey)
如果错误放进 while 循环会发生什么?
python
运行
# 错误写法,千万不要这么写
while True:
cv2.setMouseCallback('drawshape', mouse_callback)
cv2.imshow(...)
每 1ms 就重复绑定一次回调,造成:
2. 两种监听的核心区别(帮你巩固理解)
鼠标监听(setMouseCallback)
键盘监听(cv2.waitKey)
-
模式:轮询、主动查询
-
执行时机:必须放在循环内部,每隔 1ms 主动询问一次键盘有没有按键
-
位置:写在
while True循环内部1. 为什么只执行一次就永久监听?
这个函数的作用是注册绑定:
-
你告诉 OpenCV:名为
drawshape的窗口,后续所有鼠标动作,统一交给mouse_callback函数处理; -
注册完成后,OpenCV 内部会单独维护一套鼠标消息监听机制,和你的
while主循环完全分开; -
只要窗口不关闭,鼠标事件会持续自动触发回调,不需要重复注册。
-
资源冗余,程序卡顿;
-
多次重复绑定,鼠标一次动作会多次执行绘图逻辑;
-
无任何收益,纯浪费性能。
-
模式:事件驱动、被动监听
-
执行时机:程序启动只调用 1 次注册;鼠标操作时系统自动调用回调
-
位置:写在
while True循环外部 -
模式:轮询、主动查询
-
执行时机:必须放在循环内部,每隔 1ms 主动询问一次键盘有没有按键
-
位置:写在
while True循环内部