我正在用Python3制作一个mp3播放器(也使用Tkinter),但我面临着一个死胡同

我正在用Python3制作一个mp3播放器(也使用Tkinter),但我面临着一个死胡同,python,tkinter,pygame,Python,Tkinter,Pygame,我正在制作一个菜单函数,将歌曲添加到播放器中 def add_song(): song = filedialog.askopenfilename(initialdir='C:\\Users\\Soham\\Music', title="Choose a song!",filetypes=(("mp3 Files", "*.mp3"), )) song_name = song.split("/"

我正在制作一个菜单函数,将歌曲添加到播放器中

def add_song():
    song = filedialog.askopenfilename(initialdir='C:\\Users\\Soham\\Music', title="Choose a 
    song!",filetypes=(("mp3 Files", "*.mp3"), ))
    song_name = song.split("/")[-1].split(".")[0]
    song_list.insert(END, song_name)
然后,我有一个播放按钮,它被编码为播放歌曲-

play_button = Button(controls_frame, image=play_button_img,borderwidth=0, command = play)
play_button.grid(row=0,column=2,padx=5)
因此,func,
play()
的代码是-

def play():
    song = song_list.get(ACTIVE)
    pygame.mixer.music.load(song)
    pygame.mixer.music.play(loops=0)
但在这里,play()中的变量实际上只是歌曲的名称,因为它已经在add_song()中分离出来。pygame需要整个路径,因为歌曲与python文件不在同一目录中。因此pygame无法打开并播放导致错误的歌曲-

  Exception in Tkinter callback
  Traceback (most recent call last):
       File "C:\Users\Soham\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 
       1885, in __call__
       return self.func(*args)
       File "c:\Users\Soham\Desktop\HM MP.py", line 26, in play
  pygame.mixer.music.load(song)
  pygame.error: Couldn't open 'Avicii - The Nights'
那么我能做些什么呢?有没有另一种方法可以分离显示歌曲名称的路径,这样就不会给
pygame
播放音乐带来任何问题


另外,我使用的是Windows 10 Pro、高端计算机和Python 3。

您可以创建一个
dict
具有
{'song name':'file path'}
既然您要将歌曲插入列表框并从那里播放,您可以做的是,制作一个索引字典,从0开始作为键,值作为歌曲名称和路径的列表,因此它类似于
song\u dict={idx:[song\u name,song\u path]}
。因此,每个idx都是您从列表框中选择的。我举了一个例子,看看:

from tkinter import *
from tkinter import filedialog
import pygame

root = Tk()
pygame.mixer.init()

song_dict = {} # Empty dict to assign values to it
count = 0 # An idx number to it increase later
def add_song():
    global count
    
    song_path = filedialog.askopenfilename(initialdir='C://Users//Soham//Music', title="Choose a song!",filetypes=(("mp3 Files", "*.mp3"), ))
    song_name = song_path.split("/")[-1].split(".")[0]
    song_dict[count] = [song_name,song_path] # Create the desired dictionary 
    song_list.insert(END, song_name) # Insert just the song_name to the Listbox

    count += 1 # Increase the idx number 

def play_song(*args):
    idx = song_list.curselection()[0] # Get the index of the selected item
    song = song_dict[idx][1] # Get the corresponding song from the dictionary 
    pygame.mixer.music.load(song) # Load the song
    pygame.mixer.music.play(loops=0) # Play the song


song_list = Listbox(root,width=50)
song_list.pack(pady=10)

choose = Button(root,text='Choose song',command=add_song)
choose.pack(pady=10)

song_list.bind('<Double-Button-1>',play_song) # Just double click the desired song to play

root.mainloop()
尽管我也建议制作一个按钮来询问目录,并获取该目录中的所有mp3文件并填充列表框

如果要使用
filedialog.askopenfilenames
,则可以按如下方式编辑该函数:

import os

def add_song():
    songs_path = filedialog.askopenfilenames(initialdir='C://Users//Soham//Music', title="Choose a song!")

    for count,song in enumerate(songs_path):
        song_name = os.path.basename(song)
        song_dict[count] = [song_name,song] # Create the desired dictionary 
        song_list.insert(END, song_name) # Insert just the song_name to the Listbox
在这种情况下,您不需要预定义的
count
变量,因为我们从
for
循环中创建它们

编辑: 与其使用
split
,为什么不直接使用
os.path
,这样您就可以从路径中获取basename,如:

import os

song_name = os.path.basename(song_path) # If its tuple then loop through and follow

您可以创建一个字典,其中键是歌曲名称,值是文件的完整路径。然后使用该字典根据歌曲名称从字典中检索到的完整文件路径加载。是的,刚刚奏效,谢谢!当然,np,如果我在song_路径中有文件名而不是文件名,那会怎么样呢?因为这会创建一个元组,那么我该如何分割呢?因为我很确定没有什么东西可以分割tuples@CoderMan我已经更新了答案谢谢你帮了我大忙,我真的很喜欢用按钮来做导演的想法嘿,你一定认为我是个怪人,但是当我点击下一首歌的按钮时,它又给了我一个错误,任何关于这个问题的想法。抱歉问了这么多问题!这个答案是在我在评论中说的5分钟后输入的。我没有看到你的评论,也许在回答之前我没有刷新。没有什么对你不利的。从我的个人资料中可以看出,我是这方面的初学者。我花了很长时间才加上答案。此外,后来对答案进行了编辑。(这说明答案写得多么糟糕)@RufusVS
import os

song_name = os.path.basename(song_path) # If its tuple then loop through and follow