Tkinter和等待

2024-10-02 22:31:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Python3和Tkinter制作一个mp3播放器,使用pygame.mixer制作mp3。当您输入目录并按play时,它会自动查找目录中的所有MP3(使用glob),并将它们添加到列表中。我使用for循环加载然后播放音乐,但是当它播放时,它会立即开始下一首歌,并自动重复,直到列表的末尾,它只播放那首歌。我尝试使用time.sleep(),它可以工作,但会冻结程序。我怎么能等到歌曲结束后再开始下一首而不冻结节目呢

我当前的代码(仅用于播放音乐的功能):

def play():
    print("playing")
    global playing
    playing = True
    direct = directorye.get()
    direct = direct.lower()

    if direct.endswith(".mp3"):
        mixer.music.load(directorye.get())
        mixer.music.play()
    else:
        dire = r"C:\Users\agweb\Downloads\Music"  #for the time being I just hard coded the directory
        mp3s = glob.glob(dire + r"\*.MP3") # adds all MP3s in directory to list
        #mp3s =+ glob.glob(directorye.get() + "*.MP3")
        for i in mp3s:
            print(i)

            mixer.music.load(i)
            mixer.music.play()
            audio = MP3(i)
            time.sleep(audio.info.length) #works but freezes program

Tags: 目录列表forplaygettimemusicmp3
2条回答

这个解决方案可以工作,您可以测试它

from threading import Thread
import pygame
from itertools import cycle


def put_next_music_inside(loop_on_musics, stop_event):
    for cur_music in loop_on_musics:
        while pygame.mixer.music.peek(stop_event):
            pass 
        pygame.event.get(stop_event)
        pygame.mixer.music.load(cur_music)
        pygame.mixer.music.play()


pygame.mixer.init()
pygame.display.init()

END_OF_MUSIC_EVENT = -100
pygame.mixer.music.set_endevent(END_OF_MUSIC_EVENT)
list_of_music = []#fill it with musics'path
first_music = list_of_music[0]
del list_of_music[0]
list_of_music.append(first_music)
loop_on_musics = cycle(list_of_music)
t = Thread(target=put_next_music_inside, args=(loop_on_musics, END_OF_MUSIC_EVENT))
t.start()
pygame.mixer.music.load(first_music)
pygame.mixer.music.play()

有几种可能的方法

因为tkinter在Python3上是线程安全的(*),所以最简单的方法可能是启动稍微修改过的play函数作为第二个线程

在全局上下文中,创建一个threading.Event。我建议用stop_playing这个名字

在play(播放)功能中,一次仅睡眠一小段时间,检查是否设置了stop_playing

for i in mp3s:
    mixer.music.load(i)
    mixer.music.play()
    audio = MP3(i)
    playtime = 0
    interval = 100  # ms
    while playtime < audio.info.length:
        time.sleep(interval)
        playtime += interval
        if stop_playing.is_set():
            # TODO: stop the current playback.
            # Then exit the thread.
            return

“Play”按钮的新回调应该为play()start()它创建一个线程

“停止”按钮的回调应该只调用stop_playing.set()。这将导致播放线程停止

(*前提是它使用已启用线程的tcl编译。)

相关问题 更多 >