繁体   English   中英

Pygame,声音(mp3)不播放

[英]Pygame, sounds(mp3) don't play

我正在尝试使用 Pygame 和 Tkinter 播放声音文件(.mp3),但是当我启动它时,我什么也没听到。 这是代码:

from tkinter import StringVar, filedialog
import os 
import tkinter
import pygame
from pygame import *
 
root = tkinter.Tk()
path = filedialog.askdirectory()

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

def startm():
    if clicked.get() == mp3[0]:

        pygame.mixer.music.load(mp3[0])
        

if not path:
    print('Canceled')
else:
    mp3 = [fn for fn in os.listdir(path) if fn.lower().endswith('.mp3') and os.path.isfile(os.path.join(path, fn))]
    clicked = StringVar()
    tkinter.OptionMenu(root, clicked, mp3[0], *mp3).pack()

    w = tkinter.Button(root,text="start",command=startm)
    w.pack()

root.mainloop()

程序运行但声音不起作用

关于为什么音频没有播放以及为什么逻辑有缺陷,这里有几点需要注意。

  1. 没有播放音频的原因是因为您只是在加载音乐,而不是在播放它。 要播放音乐,你必须说pygame.mixer.music.play()

  2. 现在,即使您添加pygame.mixer.music.play() ,您也会注意到没有任何播放。 这是因为if条件有点毫无意义。 if clicked.get() == mp3[0]:仅当optionMenu的选择与mp3列表中的第一项相同时,该行。 但是用户应该能够播放他们选择的任何歌曲,而不仅仅是列表中的第一首歌曲。 所以你应该删除它。

  3. 现在您会注意到,尽管删除了它,但您会收到另一个错误,因为文件路径不存在。 基本上, clicked.get()将只是文件名而不是文件路径。 使用这样的文件名将强制 python 检查歌曲存在的相对路径。 但是没有相对路径使得路径为真。 所以你必须使用绝对路径。

  4. 现在使用绝对路径,您会注意到歌曲的绝对路径将显示在选项菜单中。 但你不希望这样,你只需要在选项菜单上显示歌曲名称,但你想用绝对路径播放歌曲,所以必须有某种映射,如:

{ "song_name": "D:/path/to/dir/song_name.mp3" } # Key will be displayed in optionmenu but value will be used in `pygame` to load the music.

因此,具有上述更改的代码是:

from glob import glob # (5) Mentioned in extra changes
from pathlib import Path # (6)
...
...

def startm():
    song_name = clicked.get() 
    song_abs_path = songs[song_name] # (4) Get the absolute path from the songs dictionary 
    # if clicked.get() == mp3[0]: # (2) Getting rid of this line
    pygame.mixer.music.load(song_abs_path) # (3) Loading song with its absolute path and not relative path 
    pygame.mixer.music.play() # (1) Play the song after loading it

if not path:
    print('Canceled')
else:
    mp3_abs_paths = glob(f"{path}/*.mp3") # (5) Choose all the mp3 files from the given path
    mp3_names = [Path(path).name for path in mp3_abs_paths] # (6) List of all the song names
    songs = {k:v for k,v in zip(mp3_names,mp3_abs_paths)} # (4) A dictionary in the format mentioned above above
    
    clicked = StringVar()
    tkinter.OptionMenu(root, clicked, mp3_names[0], *mp3_names).pack()

    w = tkinter.Button(root,text="start",command=startm)
    w.pack()

我上面提到的更改都标记在上面代码的注释中,以使其更易于理解。

我做了一些额外的改变:

  1. 我介绍了一个可以让你的生活更轻松的模块glob 它基本上可以替代您对mp3的列表理解所做的操作。

  2. 我使用了来自pathlibPath ,因为它在很多方面都比os.path好,而且它也使未来与路径相关的操作比os.path更简单一些。

我要做的其他事情是替换OptionMenu ,因为它有点俗气的 IMO。 ttk.Combobox是一个很好的替代品:

from tkinter import ttk

clicked = StringVar() # You can also get rid of this and start using `combo.get()` as it gives same value as `clicked.get()` and `clicked` becomes useless then.
combo = ttk.Combobox(root, values=mp3_names, state='readonly',textvariable=clicked)
combo.current(0) # Make the first item of the list as the current selection
combo.pack()

暂无
暂无

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

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