Python—实现本地音乐播放器(添加/播放/暂停/下一首/

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

1.样例

在这里插入图片描述

2.分析

  • 1.播放器界面
  • 2.功能
2.1播放器界面

在这里插入图片描述

  • button:添加/播放/暂停/下一首/上一首
  • Scale:音量条
  • Label
2.2功能
2.2.1添加音乐,选择文件夹,显示文件夹里.Mp3文件

在这里插入图片描述

def buttonAddClick():
    # 添加文件
    # 声明全局变量folder,res
    global folder
    global res
    if not folder:
        folder = tkinter.filedialog.askdirectory()
        # 列表指导式,if判断是否结尾是('.mp3','.wav','.ogg','.m4a','.flac'),识别音频文件
        # musics得到文件内容
        musics = [folder + '\\' + music for music in os.listdir(folder) if music.endswith(('.mp3'))]
        ret = []
        for i in musics:
            ret.append(i.split('\\')[1:])  # 切片,取到:后面的操作
            res.append(i.replace('\\', '/'))  # 将i张的\\替换成/,列表添加到res
        var2 = StringVar()
        var2.set(ret)  # 将ret列表去重,set集合
        lb = Listbox(window, listvariable=var2)  # 列表箱
        lb.place(x=405, y=170, width=350, height=190)
复制代码
2.2.2播放音乐,开始播放第一首音乐,按钮由"播放"变为"暂停",点击"暂停",变为"播放",播放显示Playing...

在这里插入图片描述

def buttonPlayClick():
    # 点击播放
    buttonNext['state'] = 'normal'

    buttonPrev['state'] = 'normal'
    # 选择要播放的音乐文件夹
    if pause_resume.get() == '播放':
        pause_resume.set('暂停')
        global folder

        if not folder:
            folder = tkinter.filedialog.askdirectory()
        if not folder:
            return
        global playing
        playing = True
        # 创建一个线程来播放音乐,当前主线程来接收用户操作
        t = threading.Thread(target=play)
        # start执行线程
        t.start()
    elif pause_resume.get() == '暂停':
        pygame.mixer.music.pause()
        pause_resume.set('继续')
    elif pause_resume.get() == '继续':
        pygame.mixer.music.unpause()
        pause_resume.set('暂停')
复制代码
2.2.3下一首,点击切换播放下一首音乐

在这里插入图片描述

def buttonNextClick():
    # 下一首,需要先暂停当前音乐,而主线程接收用户操作
    global playing
    palying = False
    pygame.mixer.music.stop()
    global num
    if len(res) == num:
        num = 0
    playing = True
    # 必须创建一个线程来播放音乐,当前主线程来接收用户操作
    t = threading.Thread(target=play)
    # start执行线程
    t.start()
复制代码
2.2.4上一首,点击切换播放上一首音乐

在这里插入图片描述

def buttonPrevClick():
    # 上一首
    global playing
    palying = False
    pygame.mixer.music.stop()
    global num
    if num == 0:
        num = len(res) - 2
    elif num == len(res) - 1:
        num -= 2
    else:
        num -= 2
    playing = True
    # 必须创建一个线程来播放音乐,当前主线程来接收用户操作
    t = threading.Thread(target=play)
    # start执行线程
    t.start()
复制代码
2.2.5音量,滑动控制音量

在这里插入图片描述

def control_voice(value=0.5):
    # 声音控制
    # value:0.0-1.0
    pygame.mixer.music.set_volume(float(value))
复制代码
2.2.6点击打开网页

在这里插入图片描述

# 打开超链接
def open_url(event):
    webbrowser.open("http://www.romantik.top:81/", new=0)
复制代码

3.总代码

# 导入包
import pygame
import os
import time
import threading
from tkinter import *
import webbrowser

# 导入包里的模块
import tkinter.filedialog

# 界面


# 创建一个窗口   单独运行没有反应,需要mainloop(),进入消息循环,否则显示不出
window = Tk()
# 设置窗口大小,宽x高,设置窗口的位置,基于屏幕的坐标 相对位置+x轴+y轴
window.geometry('850x405+400+100')

window.resizable(False, False)  # 固定窗体大小,不能改变
# window.attributes("-alpha",0.1)#设置窗口透明度,虚化,值越小虚化程度越高

# 窗口标题
window.title("Baby's 音乐播放器")
# 窗口置顶
# window.wm_attributes('-topmost',1)


folder = ''

res = []
num = 0
now_music = ''


def buttonAddClick():
    # 添加文件
    # 声明全局变量folder,res
    global folder
    global res
    if not folder:
        folder = tkinter.filedialog.askdirectory()
        # 列表指导式,if判断是否结尾是('.mp3','.wav','.ogg','.m4a','.flac'),识别音频文件
        # musics得到文件内容
        musics = [folder + '\\' + music for music in os.listdir(folder) if music.endswith(('.mp3'))]
        ret = []
        for i in musics:
            ret.append(i.split('\\')[1:])  # 切片,取到:后面的操作
            res.append(i.replace('\\', '/'))  # 将i张的\\替换成/,列表添加到res
        var2 = StringVar()
        var2.set(ret)  # 将ret列表去重,set集合
        lb = Listbox(window, listvariable=var2)  # 列表箱
        lb.place(x=405, y=170, width=350, height=190)

    if not folder:
        return
    # 声明全局变量,playing表示播放状态
    global playing
    playing = True
    buttonPlay['state'] = 'normal'
    pause_resume.set('播放')


def play():
    # 播放音乐
    # 混音初始化,num给播放的歌创建id
    if len(res):
        pygame.mixer.init()
        global num
        while playing:
            if not pygame.mixer.music.get_busy():
                # 随机播放一首歌曲
                nextMusic = res[num]
                pygame.mixer.music.load(nextMusic)
                # 播放一次
                pygame.mixer.music.play()
                #
                if len(res) - 1 == num:
                    num = 0
                else:
                    num = num + 1
                nextMusic = nextMusic.split('\\')[1:]
                musicName.set('playing......' + ''.join(nextMusic))
            else:
                time.sleep(0.1)


def buttonPlayClick():
    # 点击播放
    buttonNext['state'] = 'normal'

    buttonPrev['state'] = 'normal'
    # 选择要播放的音乐文件夹
    if pause_resume.get() == '播放':
        pause_resume.set('暂停')
        global folder

        if not folder:
            folder = tkinter.filedialog.askdirectory()
        if not folder:
            return
        global playing
        playing = True
        # 创建一个线程来播放音乐,当前主线程来接收用户操作
        t = threading.Thread(target=play)
        # start执行线程
        t.start()
    elif pause_resume.get() == '暂停':
        pygame.mixer.music.pause()
        pause_resume.set('继续')
    elif pause_resume.get() == '继续':
        pygame.mixer.music.unpause()
        pause_resume.set('暂停')

def buttonNextClick():
    # 下一首,需要先暂停当前音乐,而主线程接收用户操作
    global playing
    palying = False
    pygame.mixer.music.stop()
    global num
    if len(res) == num:
        num = 0

    playing = True
    # 必须创建一个线程来播放音乐,当前主线程来接收用户操作
    t = threading.Thread(target=play)
    # start执行线程
    t.start()


def closeWindow():
    # 关闭窗口
    # 有子线程和主线程,需要先结束子线程
    global playing
    palying = False
    time.sleep(0.2)
    try:
        # 停止播放,如果已经停止
        # 再次停止时,抛出异常
        pygame.mixer.music.stop()
        pygame.mixer.quit()
    except:
        pass
    window.destroy()


def control_voice(value=0.5):
    # 声音控制
    # value:0.0-1.0
    pygame.mixer.music.set_volume(float(value))


def buttonPrevClick():
    # 上一首
    global playing
    palying = False
    pygame.mixer.music.stop()
    global num
    if num == 0:
        num = len(res) - 2
    elif num == len(res) - 1:
        num -= 2
    else:
        num -= 2

    playing = True
    # 必须创建一个线程来播放音乐,当前主线程来接收用户操作
    t = threading.Thread(target=play)
    # start执行线程
    t.start()


# 打开超链接
def open_url(event):
    webbrowser.open("http://www.romantik.top:81/", new=0)

window.protocol('WM_DELETE_WINDOW', closeWindow)

# 显示框

# 添加
buttonAdd = Button(window, text='添加', font='20', activeforeground='green', command=buttonAddClick)
buttonAdd.place(x=1, y=2, width=300, height=100)

# 播放
pause_resume = StringVar(window, value="播放")
buttonPlay = Button(window, textvariable=pause_resume, font='20', activeforeground='green', command=buttonPlayClick)
buttonPlay.place(x=1, y=103, width=300, height=100)
buttonPlay['state'] = 'disabled'

# 上一首

buttonPrev = Button(window, text='上一首', font='20', activeforeground='green', command=buttonPrevClick)
buttonPrev.place(x=1, y=204, width=300, height=100)
buttonPrev['state'] = 'disabled'

# 下一首

buttonNext = Button(window, text='下一首', font='20', activeforeground='green', command=buttonNextClick)
buttonNext.place(x=1, y=305, width=300, height=100)
buttonNext['state'] = 'disabled'

musicName = StringVar(window, value='暂时没有播放音乐...')
labelName = Label(window, textvariable=musicName, font='10', fg="green")
labelName.place(x=460, y=0, width=250, height=70)

# 音量
s = Scale(window, label='音量', from_=0, to=1, orient=tkinter.HORIZONTAL,
          length=240, showvalue=0, tickinterval=2, resolution=0.1, command=control_voice)
s.place(x=430, y=70, width=300)

# 设置label标签
link = Label(window, text="点击跳转到 Baby's Blog个人博客:  www.romantik.top")
link.place(x=430, y=370)

# 绑定label单击事件
link.bind("<Button-1>", open_url)

window.mainloop()
# 功能

复制代码