简体   繁体   English

使用 pygame-change 播放音频时,python 无法在循环中中断

[英]python can't break while loop when play audio with pygame-change

I tried something new to fit the code.我尝试了一些新的东西来适应代码。 Now when I press ctrl + s the audio really stops but when my personal assistant plays music again in the same run, the music does not stop as for the first time:现在,当我按 ctrl + s 时,音频确实停止了,但是当我的个人助理在同一次运行中再次播放音乐时,音乐并没有像第一次那样停止:

import glob
import os
import keyboard

os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"

import pygame
songs = glob.glob("C:\\Users\zivsi\Music\\*.mp3")
import random

song = random.choice(songs)

with open("song_choice.txt", "r") as file:
    read = file.read()

if (read == song):
    print("switch song")
    song = random.choice(songs)

song_name = song.replace("C:\\Users\zivsi\Music\\", "").replace(".mp3", "")
print("song: ", song_name)

pygame.mixer.init()

music = pygame.mixer.music.load(song)
pygame.mixer.music.play()

while (pygame.mixer_music.get_busy()):
    pygame.time.Clock().tick(10)
    keyboard.add_hotkey("ctrl + s", lambda: pygame.mixer_music.stop())

# if i will press ctrl + s, the music will stop but it's working only once` # 如果我按下 ctrl + s,音乐将停止,但它只工作一次`

You can't use break in a different scope, it has to be part of the loop suite itself (so nested inside a while or for statement).您不能在不同的范围内使用break ,它必须是循环套件本身的一部分(因此嵌套在whilefor语句中)。 A lambda is a function, which is a different scope.一个lambda是一个函数,它是一个不同的范围。

Because you want to break out of the loop asynchronously, you'll need some other way to communicate from the keyboard callback handler back to the main loop.因为您想以异步方式跳出循环,所以您需要一些其他方式将键盘回调处理程序通信回主循环。 In general computer engineering terms, you need some kind of synchronization primitive to synchronize between different things that are happening at the same time, concurrently.在一般的计算机工程术语中,您需要某种同步原语来同步同时发生的不同事物。

That is to say, you want to set some kind of flag , one that you can check in your while loop, so while pygame.mixer_music.get_busy() and not keyboard_ctrl_s_flag: .也就是说,您想设置某种标志,您可以在while循环中检查该标志,因此while pygame.mixer_music.get_busy() and not keyboard_ctrl_s_flag: You can do this with any global value, and that'd probably be safe:您可以使用任何全局值来执行此操作,这可能是安全的:

keyboard_ctrl_s_flag = False  

def control_s_handler():
    """Called when the keyboard combination CTRL-S is pressed"""
    global keyboard_ctrl_s_flag
    keyboard_ctrl_s_flag = True

keyboard.add_hotkey("ctrl + s", control_s_handler)

then you can use that in your loop:然后你可以在你的循环中使用它:

# reset the flag to false, in case it was already set to true before
keyboard_ctrl_s_flag = False  
while pygame.mixer_music.get_busy() and not keyboard_ctrl_s_flag:
    pygame.time.Clock().tick(10)

I say this probably is safe, because I'm not quite sure how PyGame is running its event handling loop.我说这可能是安全的,因为我不太确定 PyGame 是如何运行其事件处理循环的。 Given that you also used pygame.time.Clock().tick(10) in your loop makes me think that the event loop probably waits for your Python code to return control before doing other things.鉴于您还在pygame.time.Clock().tick(10)使用了pygame.time.Clock().tick(10) ,这让我认为事件循环可能会在执行其他操作之前等待您的 Python 代码返回控制权。

The next time that the user then uses CTRL-S , the control_s_handler() callback is called, keyboard_ctrl_s_flag is set to True , and when control returns to the while loop (because pygame.time.Clock().tick(10) returned control to your Python code) the while loop exits even if pygame.mixer_music.get_busy() is still true.下次用户使用CTRL-S ,将调用control_s_handler()回调,将keyboard_ctrl_s_flag设置为True ,并且当控制返回到while循环时(因为pygame.time.Clock().tick(10)返回了控制)到您的 Python 代码)即使pygame.mixer_music.get_busy()仍然为真, while循环也会退出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM