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

Pygame时钟应用窗口关闭异常问题排查及解决方案咨询

Python模拟时钟窗口关闭异常解决方案

问题根源

你的代码中clock_hands函数包含一个无限while True循环,且内部使用time.sleep(1)阻塞程序。当点击时区按钮后,这个嵌套循环会抢占程序控制权,导致主循环无法处理pygame.QUIT事件,最终引发系统异常。

修复方案

重构代码,将指针更新逻辑整合到主事件循环中,用Pygame的时间机制替代time.sleep,确保事件始终能被处理:

修改后的完整代码

import pygame
import sys
import math
from datetime import datetime
import pytz

size = 500

pygame.init()

screen = pygame.display.set_mode((size, size))
pygame.display.set_caption("CLOCK")

font = pygame.font.SysFont("Arial", 20)

clock = pygame.time.Clock()
FPS = 60

# 初始化时区时间
tz_London = pytz.timezone("Europe/London")
datetime_London = datetime.now(tz_London)
starting_hour_London = int(datetime_London.strftime("%H"))

now = datetime.now()
starting_hour_Warsaw = int(now.strftime("%H"))
starting_minute = int(now.strftime("%M"))
starting_second = int(now.strftime("%S"))

# 计算初始角度
angle_second = int(((starting_second/60) * 360) - 90)
angle_minute = ((starting_minute/60) * 360) - 90
angle_hour_Warsaw = None
angle_hour_London = None

if starting_hour_Warsaw in range(0, 12):
    angle_hour_Warsaw = ((starting_hour_Warsaw/12) * 360 + (starting_minute * 0.5) + (starting_second * (1/120))) - 90
else:
    angle_hour_Warsaw = (((starting_hour_Warsaw - 12) / 12) * 360 + (starting_minute * 0.5) + (starting_second * (1 / 120))) - 90

if starting_hour_London in range(0, 12):
    angle_hour_London = ((starting_hour_London / 12) * 360 + (starting_minute * 0.5) + (starting_second * (1 / 120))) - 90
else:
    angle_hour_London = (((starting_hour_London - 12) / 12) * 360 + (starting_minute * 0.5) + (starting_second * (1 / 120))) - 90

# 当前选中的时区角度
current_tz_angle = None

def drawing_clock():
    screen.fill((0, 0, 0))
    pygame.draw.circle(screen, (255, 0 ,0), (size/2, size/2), 200, 10)
    lenght = 190
    offset = 150
    starting_pos = (size/2,size/2)
    angles = [0, 90, 180, 270]
    
    # 绘制刻度
    for angle in angles:
        x = starting_pos[0] + int(math.cos(math.radians(angle))) * lenght
        y = starting_pos[1] + int(math.sin(math.radians(angle))) * lenght
        pygame.draw.line(screen, (255, 0, 0), starting_pos, (x, y), 10)
    for angle in angles:
        x = starting_pos[0] + int(math.cos(math.radians(angle))) * offset
        y = starting_pos[1] + int(math.sin(math.radians(angle))) * offset
        pygame.draw.line(screen, (0, 0, 0), starting_pos, (x, y), 10)
    
    angles_2 = [30,60, 120, 150, 210, 240, 300, 330]
    for angle in angles_2:
        x = starting_pos[0] + math.cos(math.radians(angle)) * lenght
        y = starting_pos[1] + math.sin(math.radians(angle)) * lenght
        pygame.draw.line(screen, (255, 0, 0), starting_pos, (x, y), 5)
    for angle in angles_2:
        x = starting_pos[0] + math.cos(math.radians(angle)) * (offset+25)
        y = starting_pos[1] + math.sin(math.radians(angle)) * (offset+25)
        pygame.draw.line(screen, (0, 0, 0), starting_pos, (x, y), 10)
    
    # 绘制按钮
    pygame.draw.circle(screen, (255, 0, 0), (size / 8, size / 8), 40, 5)
    pygame.draw.circle(screen, (255, 0, 0), ((size / 8)*7, size / 8), 40, 5)

    button_London = font.render("London", False, (255, 255, 255))
    button_London_rect = button_London.get_rect(center = (size/8, size/8))
    screen.blit(button_London, button_London_rect)

    button_Warsaw = font.render("Warsaw", False, (255, 255, 255))
    button_Warsaw_rect = button_Warsaw.get_rect(center = ((size/8)*7, size/8))
    screen.blit(button_Warsaw, button_Warsaw_rect)

def draw_clock_hands():
    global angle_second, angle_minute, current_tz_angle
    lenght_sec = 180
    lenght_min = 150
    lenght_hours = 120
    start_pos = (size/2, size/2)

    # 绘制秒针
    x = start_pos[0] + math.cos(math.radians(angle_second)) * lenght_sec
    y = start_pos[1] + math.sin(math.radians(angle_second)) * lenght_sec
    pygame.draw.line(screen, (255, 0, 0), start_pos, (x, y), 5)
    
    # 绘制分针
    x_2 = start_pos[0] + math.cos(math.radians(angle_minute)) * lenght_min
    y_2 = start_pos[1] + math.sin(math.radians(angle_minute)) * lenght_min
    pygame.draw.line(screen, (0, 255, 0), start_pos, (x_2, y_2), 5)
    
    # 绘制时针(如果选中时区)
    if current_tz_angle is not None:
        x_3 = start_pos[0] + math.cos(math.radians(current_tz_angle)) * lenght_hours
        y_3 = start_pos[1] + math.sin(math.radians(current_tz_angle)) * lenght_hours
        pygame.draw.line(screen, (0, 0, 255), start_pos, (x_3, y_3), 5)

# 记录上次更新秒针的时间
last_second_update = pygame.time.get_ticks()

while True:
    current_time = pygame.time.get_ticks()
    
    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            # 检测伦敦按钮点击
            if (size/8)-20 < x < (size/8)+20 and (size/8)-20 < y < (size/8)+20:
                current_tz_angle = angle_hour_London
            # 检测华沙按钮点击
            elif ((size/8)*7)-20 < x < ((size/8)*7)+20 and (size/8)-20 < y < (size/8)+20:
                current_tz_angle = angle_hour_Warsaw

    # 每秒更新一次指针
    if current_time - last_second_update >= 1000:
        angle_second += 6
        if angle_second >= 360:
            angle_second = 0
        
        angle_minute += 0.1
        if angle_minute >= 360:
            angle_minute = 0
        
        if current_tz_angle is not None:
            current_tz_angle += (30/3600)
            if current_tz_angle >= 360:
                current_tz_angle = 0
        
        last_second_update = current_time

    # 重绘整个界面
    drawing_clock()
    draw_clock_hands()
    pygame.display.update()
    clock.tick(FPS)

关键修改说明

  • 移除嵌套循环:将clock_hands中的无限循环逻辑整合到主循环,确保事件处理不被阻塞
  • 替换time.sleep:用pygame.time.get_ticks()追踪时间间隔,实现非阻塞式的每秒更新
  • 全屏重绘:每次循环重新绘制整个时钟背景,替代手动擦除指针的复杂逻辑,避免画面残留
  • 状态化管理:用current_tz_angle变量维护当前选中的时区状态,无需单独函数启动循环
  • 完善退出逻辑:确保pygame.quit()在退出前被调用,释放资源

内容的提问来源于stack exchange,提问作者Kamil Gryboś

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:10:43