Pygame在循环约150次时冻结,界面停止更新如何修复?
提问:Pygame播放图片序列时窗口在约150帧后冻结,是update方法的问题吗?
我写了一段Pygame代码,本意是播放文件夹中的一系列图片,但运行时出现异常:循环会继续执行,但Pygame窗口在循环到约150次时冻结,界面停止更新;即使将帧率降低至10,问题仍会在同一帧出现。我想询问:是否是update方法的问题?有没有修复方案?pygame.display.update()是否存在调用限制?
代码如下:
import pygame from cv2 import imread # 只需要这个模块!(用于获取图像尺寸)其实也可以用pygame... image = imread("frame0.jpg") # 获取第一帧以确定视频帧的尺寸 h, w, channels = image.shape screen = pygame.display.set_mode((w,h)) # 定义显示表面 c = pygame.time.Clock() for i in range(0,4099): # 我知道这效率很低...起始帧-结束帧 im = pygame.image.load("./frame%d.jpg" % i) # 加载帧 screen.blit(im, [0, 0]) # 将图像绘制到显示表面 pygame.display.update() # 更新显示!你去哪了? screen.fill((0,0,0)) # 更新后清空画布 # 事件处理可以放在下面,因为下一循环会更新显示 print(i) # 调试输出 del im # 删除图像变量(非必需) c.tick(30) # 控制帧率!滴答滴答! print("done!")
回答
嗨,这个问题我之前踩过坑!根本原因不是pygame.display.update()的调用限制——这个方法完全可以被频繁调用,问题出在你没处理Pygame的事件队列,导致操作系统认为你的窗口“挂掉了”。
核心问题:窗口事件未处理
操作系统会定期检查窗口是否响应事件(比如鼠标移动、窗口重绘请求),如果你的代码长时间不处理这些事件,系统就会标记窗口为“未响应”,进而冻结界面。你的循环里完全跳过了事件处理,这就是为什么到150帧左右(系统判定无响应的阈值)窗口就卡住了,哪怕循环还在后台跑。
修复方案
我给你分三步解决这个问题,顺便优化下代码的性能:
1. 必须加入事件处理逻辑
在循环里加入事件处理,哪怕只是处理退出事件+清空队列,或者调用pygame.event.pump()(让Pygame内部处理系统事件)。比如:
# 在循环内部添加事件处理 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 如果不需要处理特定事件,至少加这行: # pygame.event.pump()
2. 调整绘制顺序(避免逻辑混乱)
你现在的顺序是blit → update → fill,其实应该先清空画布,再绘制新帧,最后更新显示,这样逻辑更清晰,也能减少闪烁:
screen.fill((0,0,0)) # 先清空上一帧 im = pygame.image.load("./frame%d.jpg" % i) screen.blit(im, [0, 0]) # 绘制新帧 pygame.display.update() # 更新显示
3. 提前加载所有图片(大幅提升性能)
循环里每次调用pygame.image.load()会反复读取磁盘,效率极低,建议提前把所有图片加载到列表里,循环时直接取用:
# 提前加载所有图片 frames = [] for i in range(0, 4099): frame = pygame.image.load(f"./frame{i}.jpg") frames.append(frame) # 然后循环播放 for i, im in enumerate(frames): # 事件处理... screen.fill((0,0,0)) screen.blit(im, [0,0]) pygame.display.update() print(i) c.tick(30)
修改后的完整代码
import pygame from cv2 import imread # 初始化Pygame(你之前漏了这行!) pygame.init() # 获取窗口尺寸 image = imread("frame0.jpg") h, w, channels = image.shape screen = pygame.display.set_mode((w,h)) pygame.display.set_caption("Image Sequence Player") # 提前加载所有帧(优化性能) frames = [] print("Loading frames...") for i in range(0, 4099): try: frame = pygame.image.load(f"./frame{i}.jpg") frames.append(frame) except Exception as e: print(f"Failed to load frame {i}: {e}") break c = pygame.time.Clock() running = True frame_idx = 0 while running and frame_idx < len(frames): # 处理事件(必须!) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 绘制流程 screen.fill((0,0,0)) screen.blit(frames[frame_idx], [0, 0]) pygame.display.update() print(frame_idx) frame_idx += 1 c.tick(30) pygame.quit() print("done!")
补充说明
pygame.display.update()没有调用次数限制,只要你定期处理事件,它就能持续更新界面。- 别忘了调用
pygame.init()——你之前的代码漏了这行,虽然有时能运行,但规范写法必须初始化Pygame。 - 提前加载图片不仅能提升帧率,还能避免磁盘IO导致的卡顿。
内容的提问来源于stack exchange,提问作者thomask
相关产品推荐
相关产品推荐

