python实现本地音乐播放器

代码参考了点击进入,这篇博客中每一次操作都会新建一个线程,随着操作的增加,内存中的线程会越来越多,最终导致程序崩溃,我修复了这个bug,只需一个线程就可以搞定。

# -*- coding: utf-8 -*-
"""
Created on Fri Dec  4 17:40:44 2020

@author: xin
"""
import tkinter
import os
from tkinter import *
import tkinter.filedialog
import time
import threading
import pygame

#建立一个GUI
Frame=Tk()
Frame.title("本地音乐播放器")
width=500
height=200
screenwidth = Frame.winfo_screenwidth()
screenheight = Frame.winfo_screenheight()
alignstr = "%dx%d+%d+%d" % (width, height, (screenwidth-width)/2, (screenheight-height)/2)
Frame.geometry(alignstr)
Frame.resizable(False,False)

#一些全局变量
folder = ""  #文件路径
music_dir=[]   #音乐文件路径
music_name=[]  #音乐文件名称
num=0  #当前所播放的音乐序号
playing=False  #音乐是否在播放
flag=0  #单曲循环 or 顺序播放
skip=0 #上一首下一首的标记

#选择播放音乐所在文件夹
def buttonAddClick():
    
    #global限定全局变量
    global folder
    global music_dir
    global music_name
    global playing
    #选择一个文件夹并其返回路径
    folder=tkinter.filedialog.askdirectory()
    if not folder:
        return 
    music_name.clear()
    music_dir.clear()
    #读取文件夹里的音乐文件
    for each in os.listdir(folder):
        if each.endswith((".mp3",".wav",".ogg")):
               music_name.append(each)
               music_dir.append(folder+"\\"+each)
    if(len(music_dir)==0):
        return 
    #将文件名列出到GUI上
    var=StringVar()
    var.set(music_name)
    music_list = Listbox(Frame,listvariable=var)
    music_list.place(x=200,y=40,width=260,height=150)
   
    playing = True
    buttonPlay["state"] = "normal"
    start_stop.set("播放")
    buttonAdd["state"]="disabled"
    pygame.mixer.init()
    
#播放音乐函数
def play():
    global num
    global playing
    global flag
    global skip
    if len(music_dir):
        pre=0 #上一首
        while playing:
            if not pygame.mixer.music.get_busy(): #没有音乐播放
                if flag:
                    if not skip:
                        num=pre
                skip=0
                next_music=music_dir[num]
                pygame.mixer.music.load(next_music.encode())
                pygame.mixer.music.play(1)
                musicName.set("正在播放:"+music_name[num])
                pre=num
                if len(music_dir)-1==num:
                    num=0
                else:
                    num=num+1
            else:
                time.sleep(0.1)

#播放暂停切换
def buttonPlayClick():
    buttonNext["state"] = "normal"
    buttonPrev['state'] = 'normal'
    buttonCircle['state'] = 'normal'
    if start_stop.get()=="播放":
        start_stop.set("暂停")
        #新建一个线程来后台播放音乐
        t=threading.Thread(target=play)
        t.start() 
    elif start_stop.get()=="暂停":
       pygame.mixer.music.pause()
       start_stop.set("继续")
    elif start_stop.get()=="继续":
       pygame.mixer.music.unpause()
       start_stop.set("暂停")
       
#回到上一首
def buttonPrevClick():
    global skip
    skip=1
    pygame.mixer.music.stop()
    global num
    if num==0:
        num=len(music_dir)-2
    elif num==1:
        num=len(music_dir)-1
    else:
        num-=2 
        
#切换下一首
def buttonNextClick():
    global skip
    skip=1
    pygame.mixer.music.stop()   

#播放模式的切换
def buttonCircClick():
    global flag
    if mode_change.get()=="单曲循环":
        flag=1
        mode_change.set("顺序播放")
    else:
        flag=0
        mode_change.set("单曲循环")      

#调整音量
def controlVoice(value):
    global playing
    if playing:
        pygame.mixer.music.set_volume(float(value))
        
def closeWindow():
    #playing 变 False,从而结束循环,t线程退出
    global playing
    playing = False
    time.sleep(0.3)
    if len(music_name)>0:
        pygame.mixer.music.stop() 
        pygame.mixer.quit()   
    Frame.destroy()


#设置关闭窗口协议    
Frame.protocol("WM_DELETE_WINDOW", closeWindow)           

#添加音乐按钮            
buttonAdd=Button(Frame,text="添加音乐",command=buttonAddClick)
buttonAdd.place(x=30,y=10,width=60,height=30)

#播放/暂停按钮
start_stop=StringVar(Frame, value="播放")
buttonPlay=Button(Frame,textvariable=start_stop,command=buttonPlayClick)
buttonPlay.place(x=100,y=10,width=60,height=30)
buttonPlay["state"] = "disabled"


#下一首按钮
buttonNext=tkinter.Button(Frame,text="下一首",command=buttonNextClick)
buttonNext.place(x=100,y=50,width=60,height=30)
buttonNext["state"]="disabled"

#上一首按钮
buttonPrev=tkinter.Button(Frame,text="上一首",command=buttonPrevClick)
buttonPrev.place(x=30,y=50,width=60,height=30)
buttonPrev["state"] = "disabled"

#单曲循环/循序播放按钮
mode_change=StringVar(Frame,value="单曲循环")
buttonCircle=tkinter.Button(Frame,textvariable=mode_change,command=buttonCircClick)
buttonCircle.place(x=30,y=90,width=60,height=30)
buttonCircle["state"]="disabled"

#当前播放音乐
musicName=StringVar(Frame,value="暂时没有播放音乐")
labelName=Label(Frame,textvariable=musicName,justify=LEFT,fg="red")
labelName.place(x=200,y=10,width=260,height=20)

#调节音量
labelvoice=Label(Frame,text="音量",justify=LEFT)
labelvoice.place(x=20,y=150,width=30,height=20)
s = tkinter.Scale(Frame,from_=0,to=1,orient=tkinter.HORIZONTAL,length=200,resolution=0.1,command=controlVoice)
s.set(1)
s.place(x=50, y=130 ,width=100)

#循环刷新
Frame.mainloop()

   pyinstaller打包成exe文件,详见  https://mp.weixin.qq.com/s/rL84_hBqH4CX-SmUXnjKAQ

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值