我正在使用 Python3(也使用 Tkinter)制作 mp3 付款器,但我正面临着死胡同 [英] I am making a mp3 payer in Python3 (also using Tkinter) but I am facing a dead end
问题描述
我正在制作一个向播放器添加歌曲的菜单功能.
I am making a menu func which adds songs to the player.
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)
然后我有一个播放按钮,它被编码来播放添加的歌曲 -
Then afterwards I have a play button which is coded to play the song added -
play_button = Button(controls_frame, image=play_button_img,borderwidth=0, command = play)
play_button.grid(row=0,column=2,padx=5)
所以,函数,play()
的代码是 -
So, the func, play()
's code is -
def play():
song = song_list.get(ACTIVE)
pygame.mixer.music.load(song)
pygame.mixer.music.play(loops=0)
但是这里 play() 中的 dong 变量实际上只是歌曲的名称,因为它已经在 add_song() 中分开了.而且 pygame 需要整个路径,因为歌曲与 python 文件不在同一目录中.所以pygame无法打开和播放歌曲导致错误-
But here dong variable in play() is actually just the name of song as it is already split off in add_song().And pygame needs the entire path as the song is not in the same directory as the python file. So pygame cannot open and play the song resulting in the error -
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
播放音乐创造任何问题??
So what can I do about this , is there another way where I can split off the path for displaying the song name creating no problems for pygame
to play the music??
另外,我使用的是 Windows 10 Pro、高端机器和 Python 3.
Also, I am using Windows 10 Pro , high end machine and using Python 3.
推荐答案
既然你将歌曲插入到列表框并从那里播放,你可以做的就是制作一个索引字典,索引从 0 开始作为键和值作为歌曲名称和路径的列表,所以它类似于 song_dict = {idx:[song_name,song_path]}
.因此,每个 idx 都将是您从列表框中选择的.我用这个做了一个例子,看看:
Since you are inserting the song on to the list box and play it from there, what you could do is, make a dictionary of index starting from 0 as key and values as list of song name and path, so its something like like song_dict = {idx:[song_name,song_path]}
. So each idx will be your selection from the listbox. I have made an example with this, take a look:
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()
只需双击您要播放的歌曲.您也可以使用按钮代替 bind()
,就像您在代码中所做的那样.
Just double click the song you want to play. You can also use a button instead of bind()
like you do in your code.
song_dict
的结构示例如下:
{0: ['Shawn Mendes - Perfectly Wrong', 'C:/PyProjects/sONGS/Shawn Mendes - Perfectly Wrong.mp3'],
1: ['Lil Nas X - Old Town Road (feat', 'C:/PyProjects/sONGS/Lil Nas X - Old Town Road (feat. Billy Ray Cyrus) - Remix.mp3'],
2: ['NF - Time - Edit', 'C:/PyProjects/sONGS/NF - Time - Edit.mp3']}
虽然我也建议制作一个按钮来询问目录并获取该目录中的所有 mp3 文件并填充列表框.
Though I would also recommend to make a button to ask for directory and take all the mp3 files in that directory and populate the listbox.
如果你想使用 filedialog.askopenfilenames
那么你可以编辑如下函数:
If you want to use filedialog.askopenfilenames
then you can edit the function as below:
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
循环中创建它们.
In this case you don't need the pre defined count
variable, as we make them from the for
loop.
与其使用 split
,不如使用 os.path
,这样您就可以从路径中获取基本名称,例如:
Instead of using split
, why not just use os.path
, so you can get the basename from the path, like:
import os
song_name = os.path.basename(song_path) # If its tuple then loop through and follow
这篇关于我正在使用 Python3(也使用 Tkinter)制作 mp3 付款器,但我正面临着死胡同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!