You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:40:52