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

Pygame摆锤模拟程序失焦(切出窗口)时崩溃无响应

摆锤模拟窗口失焦崩溃问题修复方案

问题根源

你的代码核心问题出在主循环被长时间阻塞:

  • simulatePendulum方法内部包含一个长达100万次的循环(tMax=10000、dt=0.01,计算下来循环次数近百万),每次主循环调用这个方法时,程序会死死卡在这个循环里,完全无法处理Pygame的系统事件(包括窗口失焦、最小化、关闭等)。
  • 系统检测到窗口长时间没有响应事件,就会判定窗口崩溃;而控制台因为数学计算在后台持续运行,所以能正常输出。
  • 同时存在重复渲染:simulatePendulum里每步调用draw,主循环又再次调用draw,造成冗余的资源消耗。

修复后的完整代码

import pygame
import numpy as np


pygame.init()
WIDTH = 800
HEIGHT = 500
res = (WIDTH, HEIGHT)
screen = pygame.display.set_mode(res)
clock = pygame.time.Clock()
WHITE = [255, 255, 255]
RED = [255,0,0]
BLACK = [0, 0, 0]
BLUE = [0, 0, 155]


class Pendulum:
    def __init__(self, theta0, L, dt, pivot, bobMass):
        self.g = 9.81
        self.theta = theta0 
        self.L = L  
        self.dt = dt  
        self.pivot = pivot
        self.bobMass = bobMass
        # 初始化角速度和当前位置
        self.omega = 0.0
        self.x = self.L * np.sin(self.theta)
        self.y = self.L * np.cos(self.theta)

    def update(self):
        # 逐帧更新摆锤状态(每次只计算一步)
        self.omega += self.dt * (-self.g / self.L * np.sin(self.theta))
        self.theta += self.dt * self.omega
        self.x = self.L * np.sin(self.theta)
        self.y = self.L * np.cos(self.theta)

    def draw(self):
        bobPos = (self.x + 400, self.y + 300)
        pivotPos = (self.pivot[0] + 400, self.pivot[1] + 300)
        screen.fill(WHITE)
        pygame.draw.line(screen, RED, pivotPos, bobPos, 2)
        pygame.draw.circle(screen, BLUE, pivotPos, 5)
        pygame.draw.circle(screen, BLACK, bobPos, 10)
        pygame.display.update()
        
    
def main():
    theta0 = np.pi/4
    L = 100
    dt = 0.01
    pivot =(0,0)
    bobMass=1
    p = Pendulum(theta0, L, dt, pivot, bobMass)

    done = False
    while not done:
        # 优先处理所有事件,确保窗口能响应系统操作
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            # 可选:检测窗口焦点状态,可扩展暂停/继续功能
            elif event.type == pygame.ACTIVEEVENT:
                if event.gain == 0:
                    print("窗口失焦")
                else:
                    print("窗口恢复焦点")

        # 逐帧更新摆锤状态并渲染
        p.update()
        p.draw()
        
        clock.tick(60)
    pygame.quit()

if __name__ == "__main__":
    main()

关键修复说明

  1. 拆分模拟逻辑:

    • 移除了一次性跑完所有模拟步骤的simulatePendulum方法,换成逐帧更新的update方法,每次主循环只计算一步摆锤状态,彻底避免阻塞事件处理流程。
    • 让类内部保存摆锤的当前状态(角度、角速度、位置),不再预计算所有时间点的数据。
  2. 统一渲染流程:

    • 把draw调用移到主循环中统一执行,移除模拟过程中的重复渲染,减少资源浪费。
  3. 强化事件处理:

    • 确保事件循环在主循环中优先执行,让程序能及时响应窗口失焦、最小化等系统事件,避免被判定为无响应。
    • 可选添加了ACTIVEEVENT事件监听,方便扩展窗口失焦时暂停模拟的功能。
  4. 精简冗余代码:

    • 移除了tMax、scale、pivotRadius等未实际使用的参数,简化代码结构。

内容的提问来源于stack exchange,提问作者Archie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:45:00