pygame中pg.mixer.music.get_busy()在音乐播放时返回False,且取消暂停会跳过当前音乐的问题求助
pygame中pg.mixer.music.get_busy()在音乐播放时返回False,且取消暂停会跳过当前音乐的问题求助
我来帮你分析问题根源,以及对应的修复方案:
核心问题1:错误使用play()恢复暂停的音乐
你当前在取消暂停时调用pg.mixer.music.play(0)是完全错误的操作:
play()方法会从头开始播放当前加载的音乐,而不是从暂停位置继续- 更关键的是,这个调用存在时间差问题:在同一帧中,
pg.mixer.music.get_busy()可能还没来得及更新为True,就触发了下一首歌曲的加载逻辑,直接导致当前歌曲被跳过
正确的恢复暂停操作应该使用pg.mixer.music.unpause(),它会直接从暂停位置继续播放,并且会立即将get_busy()的状态更新为True。
核心问题2:get_busy()的特性与逻辑冲突
pg.mixer.music.get_busy()的设计特性是:当音乐处于暂停状态时,它会返回False。你当前的下一首加载逻辑是:
if Mlist and not(pg.mixer.music.get_busy()) and not(pause):
这个条件本身逻辑是成立的(暂停时pause为True,不会触发加载),但错误的恢复播放方式(用play()而非unpause())导致在取消暂停的瞬间,get_busy()还保持False,同时pause被设为False,刚好满足加载下一首的条件,最终导致当前歌曲被跳过。
修复后的完整代码
import os import pygame as pg from random import shuffle # 获取音乐列表并打乱顺序 Mlist = os.listdir("playlist") shuffle(Mlist) pg.init() # 显式初始化混音器,避免环境兼容性问题 pg.mixer.init() size = [800, 600] screen = pg.display.set_mode(size) clock = pg.time.Clock() pause = False running = True current_song_idx = 0 # 用索引跟踪播放位置,比随机选择+删除更高效 while running: for event in pg.event.get(): if event.type == pg.QUIT: running = False if event.type == pg.KEYDOWN: if pause: # 正确的取消暂停方式:从暂停位置继续播放 pg.mixer.music.unpause() pause = False else: pause = True pg.mixer.music.pause() # 播放下一首的逻辑:列表非空、音乐未在播放、未处于暂停状态 if Mlist and not pg.mixer.music.get_busy() and not pause: if current_song_idx < len(Mlist): song = Mlist[current_song_idx] current_song_idx += 1 pg.mixer.music.load(f"playlist/{song}") pg.mixer.music.play() else: # 所有歌曲播放完毕,可根据需求改为循环播放或退出 # 示例:重置索引重新循环 current_song_idx = 0 shuffle(Mlist) pg.display.flip() clock.tick(30) # 规范退出方式 pg.quit()
额外优化建议
- 显式初始化
pg.mixer.init():虽然pg.init()会初始化所有模块,但显式初始化混音器能避免部分环境下的兼容性问题 - 用索引遍历列表:比每次
choice+remove的效率更高,且能确保每首歌只播放一次(如需随机可在循环时重新打乱) - 歌曲循环逻辑:示例中在所有歌曲播放完毕后重置索引并重新打乱列表,你可以根据需求调整为停止播放或其他逻辑
这样修改后,暂停/恢复功能会正常工作,不会再出现取消暂停时跳过当前歌曲的问题。
备注:内容来源于stack exchange,提问作者Bublek
相关产品推荐
相关产品推荐

