-2

我正在制作一个计时器程序,我希望它在计时器结束时播放一首歌曲,但我也想在按下按钮时停止声音。

我看过其他使用多处理模块(如何使用 playsound 模块停止音频?)来停止音频的帖子,但我已经在使用线程模块,所以我想知道是否可以使用它来停止音频。

编辑:Matiis 提供了一个与我正在寻找的不同的解决方案,但它仍然可以完美运行。荣耀9211 也提供了我稍后寻找的解决方案

from tkinter import *
from time import sleep
from threading import Thread
from threading import Event

import playsound

class App(Tk):

    def __init__(self):
        super().__init__()
        self.title("Clock")
        self.t_evt = Event()

        self.frame2 = Frame(self)

        self.timerStart = Button(self.frame2, text="Start", command=self.tt_Start)
        self.timerStart.config(height=2, width=5)
        self.timerStart.grid(row=1)

        self.timerEnd = Button(self.frame2, text="End", command=self.timer_End)
        self.timerEnd.config(height=2, width=5)
        self.timerEnd.grid(row=2)


    def tt_Start(self):
        t = Thread(target=self.timer_Start)
        t.setDaemon(True)
        t.start()

    def timer_Start(self):
        self.t_evt.clear()
        timer_seconds = int(self.timerS_Entry.get())
        timer_minutes = int(self.timerM_Entry.get())
        if timer_seconds > 59:
            timer_seconds -= 60
            timer_minutes += 1
        while not self.t_evt.is_set():
            print(f"Minutes: {timer_minutes}, Seconds: {timer_seconds}")
            self.timerSeconds.config(text=timer_seconds)
            self.timerMinutes.config(text=timer_minutes)
            self.update()
            time = (timer_minutes * 60) + timer_seconds
            timer_seconds -= 1
            sleep(1)
            if time == 0:
                break
            if timer_seconds < 0:
                timer_seconds = 59
                timer_minutes -= 1

        playsound.playsound('C:\\Users\\nonon\\mp3\\song.wav')
        print("TIMER UP")
        return

    def timer_End(self):
        self.t_evt.set()

这里有一些代码供您使用,如果您需要更多代码,请告诉我。

同样,我希望能够playsound.playsound('C:\\Users\\nonon\\mp3\\song.wav')在按下结束按钮时停止

4

1 回答 1

0

简答

您可以使用线程Events而不是线程。或切换到多处理并使用p.terminate()

长答案

您不能使用任何提供的函数停止 python threading.Thread。人们使用标志来实现这一点。好读: 有没有办法杀死一个线程?

IE


def thread_func():
    while flag:
        print("I'm running")

def run_button():
    flag = True
    t = threading.Thread(target=thread_func)
    t.start()

def stop_button():
    flag = False
    # This will make the function exit

但是在您的情况下, playsound 函数不是循环函数,您可以在其中潜入一个标志来停止该函数。你可以想象它是无限期的睡眠功能,即

def play_sound():
    time.sleep(1000000) # Replacing with playsound.playsound

所以使用 threading.Events() 我们可以用这个示例代码实现这一点

import random
import signal
import threading
import time

exit_event = threading.Event()


def bg_thread():
    for i in range(1, 30):
        print(f'{i} of 30 iterations...')
        if exit_event.wait(timeout=random.random()):
            break

    print(f'{i} iterations completed before exiting.')


def signal_handler(signum, frame):
    exit_event.set() # same as setting the flag False


signal.signal(signal.SIGINT, signal_handler)
th = threading.Thread(target=bg_thread)
th.start()
th.join()

此解决方案有效地为您提供“可中断”睡眠,因为如果在线程卡在调用 wait() 中间时设置了事件,则等待将立即返回。

在此处阅读详细示例:https ://blog.miguelgrinberg.com/post/how-to-kill-a-python-thread

于 2021-12-22T09:57:46.530 回答