Python Time.Sleep()正在冻结我的pygame窗口并冻结我的函数

Python Time.Sleep()正在冻结我的pygame窗口并冻结我的函数,python,python-3.x,time,pygame,sleep,Python,Python 3.x,Time,Pygame,Sleep,所以我遇到了一个大问题,5个小时以来我一直在研究这个问题,没有取得任何进展,这就是为什么我现在要问这个问题。在底部你可以看到代码,在那里我得到了我的问题。 所以它的基本功能是:它打开一个pygame窗口,有3个按钮:一个是开始,一个是停止,一个是退出 当你按下“开始”按钮时,一个循环应该运行,它每x秒播放一次声音,直到你按下“停止”按钮。 问题是,time.sleep()确实冻结了整个窗口。是的,我做了很多研究,但我没有为自己得出结论。。。我是python的初学者,我做了大约两周。这也是我在这个

所以我遇到了一个大问题,5个小时以来我一直在研究这个问题,没有取得任何进展,这就是为什么我现在要问这个问题。在底部你可以看到代码,在那里我得到了我的问题。 所以它的基本功能是:它打开一个pygame窗口,有3个按钮:一个是开始,一个是停止,一个是退出

当你按下“开始”按钮时,一个循环应该运行,它每x秒播放一次声音,直到你按下“停止”按钮。 问题是,time.sleep()确实冻结了整个窗口。是的,我做了很多研究,但我没有为自己得出结论。。。我是python的初学者,我做了大约两周。这也是我在这个社区的第一篇帖子,很抱歉,如果这篇帖子不一样的话!:p

我想要的是,当Tonemaker循环运行时,pygame窗口保持活动状态,您可以单击其他按钮

如果你需要更多的信息,尽管问吧! 谢谢你的帮助!我真的很感激每一个答案,因为我现在真的被卡住了

import pygame, threading
from pygame import *
import time


run = True
distance = int(input("What Distance you wanna Run? [Meters]:"))
timer = int(input("How fast do you wanna Run it? [Seconds]:"))  
frequence = int(input("The Tone should come every? [Meters]:")) 
# Ask all the needed informations and save them as Variables 

tonerepeats = distance / frequence
tonetimer = timer / tonerepeats  # Calculate the time the progam should wait inbetween the sounds
tonetimer = float(tonetimer)  # make the tonetimer an float (number)  important, otherwise sleep will give an error


pygame.init()
displaywidth = 800
displayheight = 800
black = (0, 0, 0)
grey = (30, 30 ,30)
white = (255, 255, 255)              #stuff for the pygame window
red = (200, 0, 0)
green = (0, 200, 0)
brightgreen = (0, 255, 0)
brightred = (255, 0, 0)

gameDisplay = pygame.display.set_mode((displaywidth, displayheight))
pygame.display.set_caption("Tulsa Driller 1.0")
clock = pygame.time.Clock()
tulsaimg = pygame.image.load("D:/python/tulsa.png")


def Tonemaker():                                                #the loop for the playsound function
    while run == True:  # as long as run is true do this
        pygame.mixer.init()  # needed line for playing an sound
        pygame.mixer.music.load("D:/python/sound.wav")  # load up the sound from libarys
        pygame.mixer.music.play(0)  # play the sound (0 = play 1 time) (1= play infinite)
        time.sleep(tonetimer)
          # After playing the sound wait x time till play it again
        clock = pygame.time.Clock()  # needed line for pygame to work
        clock.tick()  # needed line for pygame to work
        while pygame.mixer.music.get_busy():  # avoid errors with the playsound. "while the sound is playing do nothing"
            pygame.event.poll()
            clock.tick()





def tu(x,y):
    gameDisplay.blit(tulsaimg, (x,y))

x = (displaywidth*0.25 )
y = (displayheight*0.25 )

def text_objects(text, font):
    textSurface = font.render(text, True, white)
    return textSurface, textSurface.get_rect()
def button(msg,x,y,w,h,ic,ac,action=None):                 #function for the buttons
    mouse= pygame.mouse.get_pos()
    click= pygame.mouse.get_pressed()


    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay, ac, (x, y, w, h))
        if click[0] == 1 and action !=None:
            if action == "start": Tonemaker()           # if you press start it starts the loop
            elif action== "stop": run= False            #if you press stop the loop will stop
            elif action== "quit": quit()                #quit the program, when quit button is pressed


    smalltext = pygame.font.Font("freesansbold.ttf", 20)
    textSurf, textRect = text_objects(msg, smalltext)
    textRect.center = ((x + (w / 2)), (y + (h / 2)))
    gameDisplay.blit(textSurf, textRect)



crashed = False

while not crashed:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True



    gameDisplay.fill(grey)
    tu(x, y)

    button("Start",150,650,100,50,green,brightgreen,"start")
    button("Stop", 350, 650, 100, 50, red, brightred,"stop")       #the 3 buttons
    button("Quit", 550, 650, 100, 50, red, brightred,"quit")

    pygame.display.update()
    clock.tick(75)

pygame.quit()
quit()

看看你是否能从下面的代码片段中得到一些启发。 我不是pygame的开发者。但我相信这个概念,它应该按照下面提到的思路进行编码

import threading
import time

class SoundThread(threading.Thread):
    def __init__(self):
        self.quit = False
        self.event = threading.Event()  # Whenever this event is set, play sound
        self.event.clear()  # By default no sound should be played
        threading.Thread.__init__(self)

    def run(self):
        while not self.quit:
            eventSet = self.event.wait(timeout=1)
            if not eventSet:
                print("Skipping playing the sound")
                continue

            if self.quit:
                break
            # Play sound over here
            print("Play the sound")
            time.sleep(1)

    def begin(self):
        self.event.set()

    def halt(self):
        self.event.clear()

    def quit(self):
        self.quit = True


obj = SoundThread()
obj.start() # Launches a separate thread which can be controlled, based upon calls to begin, halt, and quit


# And add the below to wherever you have the action handlers.
if action == "start": obj.begin()
elif action== "stop": obj.halt()
elif action== "quit": obj.quit()

下面是一种方法,它结合了您已有的主循环。它检查循环中每个迭代的时间。如果经过足够的时间,它将调用
Tonemaker()
函数。(省略了不相关的代码)


你需要创建一个单独的线程来触发声音的开启和关闭。。现在,
Tonemaker
正在主线程中运行。现在,您可以使用它触发另一个单独的线程来处理噪声生成,而不是永远阻止Tonemaker。好的。我已经试过用线做某事了。。但它并没有真正起作用。我怎么做一个单独的线程来做这个?我认为你不需要一个单独的线程。在未崩溃时,您已经有一个常量循环:…。只需检查该循环中的当前时间,并在1秒后调用该函数。重复。过一会儿让我分享一些示例代码。。不是专门针对pygame的,只是为了帮助你理解这个概念……好的。听起来不错。你到底是什么意思。那么我该如何检查当前时间呢?但是你必须根据自己的需要调整它。。我不认为你能用它straighaway是的。所以我现在实现了你的代码行,并更改了所有链接,它成功了,谢谢!!!这叫什么?你在那里用的是什么??我想学习如何使用它。例如,我不知道self.event.set()到底做了什么。这是线程的一部分吗?哇!恭喜你让它工作了。。您应该阅读互斥、事件、锁和信号量等概念。这里我们使用了事件的概念,这是一种线程安全的方式来设置标志。也可以阻止那个事件。如果你能对我的答案投赞成票,我将不胜感激,因为它对你有用!谢谢。试过这种方法,也奏效了!谢谢大家的帮助
import time

last_time = None
# Start the timer
def StartTone():
    last_time = time.time()
    ToneMaker()
# Stop the timer
def StopTone():
    last_time = None
# Play the sound
def Tonemaker():
    pygame.mixer.init()  # needed line for playing an sound
    pygame.mixer.music.load("D:/python/sound.wav")  # load up the sound from libarys
    pygame.mixer.music.play(0)  # play the sound (0 = play 1 time) (1= play infinite)


while not crashed:
    # Other stuff.....

    # Check elapsed time if timer is running
    if last_time != None:
        now = time.time()
        # Has time elapsed?
        if now - last_time >= tonetimer:
            Tonemaker()
            # Reset
            last_time = now