这是一个学习笔记。市面上的播放器很多,所以为什么要做这件事呢,一点是希望在做这个软件的过程中学到一些知识,还有是因为像酷狗、QQ音乐这些软件经常在网上被爆出恶意删除本地音频的行为,而groove没办法播放歌词,千千静听算是比较好的一个本地播放设备了,但是总归没有自己写来的自由。
本文实现了一个在ubuntu平台下正常可执行文件封装的几乎全格式音乐播放器;在win平台下由于pydub的FFmpeg依赖会弹出命令行,由于水平限制,目前仅能实现有命令行窗口的exe封装。对于本文的不足,希望各位指教。
总共分为三个文件:
all_music.py 基于pydub,用于获得音乐类,可实现歌曲载入、播放、长度获取、播放时间获取、倍速播放、暂停、终结所有播放进程、播放状态获取等功能
show2.py 基于tkinter,用于播放器界面的可视化,之后预期添加音量加减,喜欢列表等功能。
main2.py 居中调度,用于传递文件路径,获取歌词和歌曲列表等功能。
使用pyinstaller -w -F -n 目标名称 文件名称的方式(比如这里是pyinstaller -w -F -n my_music main2.py)进行打包。
笔者经过了很多次的尝试,在网上也找了很多的方法,但都没办法修改这个图标,我看到一篇文章,貌似是因为Ubuntu系统限制,无法修改这个图标,不知道大家有没有什么办法。
笔者直接在/usr/share/application这儿新建了一个My_Music.desktop 文件链接了这个可执行文件和图片,所以就有了如下效果:
My_Music.desktop设置如下:
[Desktop Entry] #必须要的,告诉系统这是什么 Version=1.0 #可选,显示版本信息 Name=My_Music #软件名称 Comment=A Music Player #鼠标放在图标上时显示的文字 Exec=/home/xiaobai/Desktop/my_music/my_music #可执行文件路径(绝对路径) Icon=/home/xiaobai/Desktop/my_music/My_Music.jpeg #希望作为软件图标使用的图片,这张是百度的,最好是正方形,也可以下下来自己裁 Encoding=UTF-8 #可选,编码方式 StartupNotify=true #现在还不清楚有什么用 Terminal=false #是否打开命令行 Type=Application #类型 Categories=Audio;Player #类别,这里选的是音乐播放器,具体可选值可自行百度
from tkinter import filedialog import show2 import os import numpy as np import copy import all_music import time import random list_music=[] flag_list_music=0 def openfile(): #打开一个文件 global list_music,flag_list_music filenames=filedialog.askopenfilenames(title = "音乐播放器",\ filetypes =[("常见文件",\ ["*.wma","*.wav","*.mp3","*.flac",\ "*.ape","*.mp4","*.m4a","*.ogg",\ "*.flv"]),\ ("MP3文件","*.mp3"),\ ("FLAC文件","*.flac"),\ ("APE文件","*.ape"),\ ("WAV文件","*.wav"),\ ("MP4文件","*.mp4"),\ ("M4A文件","*.m4a"),\ ("OGG文件","*.ogg"),\ ("FLV文件","*.flv"),\ ("AIFF文件","*.aiff"),\ ("WMA文件","*.wma"),\ ("所有文件","*.*")]) if filenames: for f in filenames: #将音乐列表导入 list_music.append(f) if (not music.get_busy()) and len(list_music): try: music.load(list_music[0]) except: pass music.play() elif not len(list_music): assert False,"未导入任何歌曲" flag_list_music=1 #成功导入音乐 def openpath(): #导入一个目录下常见音乐文件,不包括子目录下文件 global list_music,flag_list_music path=filedialog.askdirectory(title = "音乐播放器") if path: #如果选择了文件 list_music1=os.listdir(path)#保存选择的音乐列表并修正为绝对路径 for i in range(len(list_music1)): list_music1[i]=path+"/"+list_music1[i] list_music2=copy.deepcopy(list_music1)#深拷贝 for f in list_music2: #移除不支持的格式的音乐 extension = os.path.splitext(f)[-1] if not (extension==".mp3" or\ extension==".wma" or\ extension==".wav" or\ extension==".ogg" or\ extension==".flv" or\ extension==".mp4" or\ extension==".aiff" or\ extension==".ape" or\ extension==".m4a" or\ extension==".flac"): list_music1.remove(f) print(f+"因为不被支持被移除了") list_music=list_music+list_music1 if (not music.get_busy()) and len(list_music): try: music.load(list_music[0]) except: pass music.play() elif not len(list_music): assert False,"未导入任何歌曲" flag_list_music=1 #成功导入音乐 def next_music(): #下一首歌 global list_music,flag_list_music music.stop() music.unload() way=show1.play_way.get() #获取设定的播放方式 if way==2: #列表播放 list_music.pop(0) elif way==1: #单曲循环 if len(list_music)>1: list_music.pop(0) print("单曲循环中") elif way==3: #列表循环 list_music.append(list_music.pop(0)) elif way==4: #随机播放 random.shuffle(list_music) else: assert False,"播放方式出错" flag_list_music=1 #刷新显示 if len(list_music): music.load(list_music[0]) music.play() else: assert False,"没有下一首了" def stop(): #停止播放并清空播放列表 global list_music,flag_list_music list_music=[] music.stop() music.unload() flag_list_music=1 #刷新显示 lrc_dict={} def get_lrc_geci(): #尝试打开歌曲歌词文件 global lrc_dict,list_music if list_music: path=copy.deepcopy(list_music[0])#深拷贝 for i in range(len(path)-1,-1,-1): if path[i]==".": path=path[:i]+".lrc" try: file=open(path, "r", encoding="utf-8") lrc_list = file.readlines() # '[01:48.00],[00:24.00],怀著冷却了的心窝飘远方' # 创建字典,存放歌词和时间,key表示时间,value表示歌词 lrc_dict = {} # 遍历所有元素,干掉方括号 for i in lrc_list: # 取出方括号并切割歌词字符串 lrc_word = i.replace("[", "]").strip().split("]") # 得到的结果: lrc_word = ['', '01:40.00', '', '00:16.00', '今天我寒夜里看雪飘过'] for j in range(len(lrc_word) - 1): if lrc_word[j]: time=0 for k in range(len(lrc_word[j])): try: if lrc_word[j][k]==":": time=int(lrc_word[j][:k])*60*1000+time elif lrc_word[j][k]==".": time=int(lrc_word[j][3:k])*1000+time time=int(lrc_word[j][k+1:])+time break except: print(lrc_word[j]) lrc_dict[time] = lrc_word[-1] lrc_dict["time"]=list(lrc_dict.keys()) print("get_lrc") file.close() except: lrc_dict = {} now_word=0 def get_word(): #获取当前时间的歌词 global lrc_dict,now_word if lrc_dict and music.get_busy(): for i in range(len(lrc_dict["time"])): if lrc_dict["time"][i]<=get_real_time()*music.speed\ and ((len(lrc_dict["time"])==lrc_dict["time"].index(lrc_dict["time"][i])+1\ or (len(lrc_dict["time"])>lrc_dict["time"].index(lrc_dict["time"][i])+1 \ and lrc_dict["time"][i+1]>get_real_time()*music.speed))): now_word=lrc_dict["time"][i] word=[] word.append(lrc_dict[now_word]) if len(lrc_dict["time"])>=lrc_dict["time"].index(lrc_dict["time"][i])+2: word.append(lrc_dict[lrc_dict["time"][lrc_dict["time"].\ index(now_word)+1]]) return word elif not lrc_dict: return ["暂无歌词"] else: return [] def get_real_time(): #获取歌曲播放的真实时间 return music.get_play_time() def my_mainloop(): #主循环 global list_music,flag_list_music global event1,now_word word=get_word() #获取当前时间歌词 if word: show1.get_word(lrc_word=word) event1=music.pop_event() if event1: #仅当歌曲正常结束时,event1事件触发 print("over") flag_list_music=1 #载入新歌歌词 if len(list_music): #如果还有歌 show1.set_time=0 way=show1.play_way.get()#获取设定的播放方式 if way==2: #列表播放 list_music.pop(0) elif way==1: #单曲循环 print("单曲循环中") elif way==3: #列表播放 list_music.append(list_music.pop(0)) elif way==4: #随机播放 random.shuffle(list_music) else: assert False,"播放方式出错" print("pop") if len(list_music): music.unload() music.load(list_music[0]) music.play() else: print("歌单空了") if flag_list_music: #如果需要读入歌单 now_word=0 get_lrc_geci() #获得歌词 list_music_change=copy.deepcopy(list_music)#深拷贝 path="" for j in range(len(list_music_change)): #得到歌曲名称 f=list_music_change[j] x=-1 for i in range(len(f)): if f[i]=="/": x=i if x>=0: path=list_music_change[j][:x+1] list_music_change[j]=list_music_change[j][x+1:] show1.get_music_list(path=path,list_music=list_music_change) flag_list_music=0 if get_real_time()>=0: if ((get_real_time()!=show1.music_time_scale.get()))and \ not show1.mouse_left_click: #print("set_time2") show1.set_length_and_now_time(now_time=get_real_time()) show1.music_time_scale.set(get_real_time()) show1.win.after(100,my_mainloop) def main(): global show1 global music music=all_music.all_music() #创建all_music类 music.set_event(event=1) #设置事件 show1=show2.show() #创建GUI窗口 show1.get_music(music=music,\ openfile=openfile,openpath=openpath,\ next_music=next_music,stop=stop)#传递一些函数给show类 event1=False show1.win.after(100,my_mainloop) #将主循环导进来 show2.mainloop() music.stop() #关闭GUI前停止播放 if __name__ == '__main__': main()
from pydub import AudioSegment from pydub.playback import play import multiprocessing import time import psutil def terminate(process_pid): #终结进程和其子进程 process=psutil.Process(process_pid) p_child=process.children() # 子进程列表 for p_c in p_child: p_c.kill() process.kill() def suspend(process): #休眠进程和其子进程 p_child=process.children() # 子进程列表 for p_c in p_child: p_c.suspend() process.suspend() def resume(process): #让进程和其子进程复苏 p_child=process.children() # 子进程列表 for p_c in p_child: p_c.resume() process.resume() class all_music(): #all_music类 def __init__(self): self.song_path=[] #歌曲路径 self.song=[] #导入的歌曲 self.process1=[] #播放进程 self.suffix=[] #歌曲类型 self.now_time=-1 #当前播放歌曲的时长 self.start_time=-1 #计时器开始计时的时间 self.excursion_time=0 #偏移时间,在偏移播放和暂停时用来获取真实播放时间 self.length=-1 #歌曲长度 self.load_flag=0 #加载状态 self.busy=0 #0:空闲;1:播放中;2:暂停中;3:暂停准备继续播放 self.event=0 #事件 self.speed=1 #速度 def set_event(self,event): #设置事件返回值,触发时返回event,未触发返回0 self.event=event def pop_event(self): #查看当前事件状态,播放完毕则返回设置的event,否则返回0 try: result=self.q.get(block=False) self.busy=0 return result except: return 0 def pydub_play(self): #播放音乐并在结束时触发事件 play(self.song) self.q.put(self.event,block=True) def get_busy(self): #查看是否忙碌 return self.busy def get_length(self): #得到歌曲长度 return self.length def pos_set(self,time): #设置歌曲播放位置 if self.load_flag: self.stop() self.play(start=time) else: assert False,"未载入歌曲" def get_play_time(self): #获得当前歌曲播放到的位置 if self.start_time!=-1: if self.busy==1: #判断是否在暂停状态 #当前歌曲播放了多少毫秒 self.now_time=self.excursion_time+int((time.time()-self.start_time)*1000) #print("播放中,time=%d"%self.now_time) return self.now_time else: #print("暂停中,time=%d"%self.now_time) return self.now_time else: #print("歌曲未开始") return -1 def load(self,file_path): #获得路径 if not self.load_flag: #判断是否已经加载了歌曲 if file_path: #判断路径是否为空 self.song_path=file_path #将歌曲路径给到self for i in range(len(self.song_path)-1,-1,-1): #寻找文件后缀 if self.song_path[i]==".": break if self.song_path[i]==".": #将歌曲后缀给到self self.suffix=self.song_path[i+1:] self.load_flag=1 else: assert False,"未发现文件后缀" else: assert False,"load(file_path)需要一个歌曲路径" else: assert False,"已经加载了一个歌曲" def unload(self): #解除加载状态 if self.load_flag: #判断是否已经加载了歌曲 self.load_flag=0 self.song_path=[] self.suffix=[] else: assert False,"未加载歌曲" def set_speed(self,speed): self.speed=speed def play(self,start=0): #播放歌曲 #判断歌曲是否在播放或者暂停状态 if (self.busy==0 or self.busy==3)and self.load_flag: if self.suffix:#是否有下标 if self.suffix=="mp3": #导入mp3歌曲 self.song = AudioSegment.from_mp3(self.song_path) elif self.suffix=="ogg": #导入ogg歌曲 self.song = AudioSegment.from_ogg(self.song_path) elif self.suffix=="flv": #导入flv歌曲 self.song = AudioSegment.from_flv(self.song_path) else:#导入其他支持的格式的歌曲 try: self.song = AudioSegment.from_file(self.song_path,self.suffix) except: assert False,"不支持的文件或不存在此文件" if self.speed!=1: self.song = self.song._spawn(self.song.raw_data, \ overrides={"frame_rate": int(self.song.frame_rate * self.speed)})\ .set_frame_rate(self.song.frame_rate) if start>len(self.song): assert False,"设置的时间超过歌曲的时长" self.excursion_time=start #设置偏移时间归零 self.now_time=self.excursion_time#设置播放时间归零 self.busy=1 self.length=len(self.song) #设置歌曲时长 if self.now_time: self.song=self.song[self.now_time:] self.q = multiprocessing.Queue(maxsize=1) self.process1 = multiprocessing.Process(target =self.pydub_play,name="my_process1") self.process1.start() self.start_time=time.time() else: assert False,"未载入任何歌曲" else: assert False,"歌曲未载入或占用中,请先load或stop" def stop(self): #结束播放但不unload if self.busy: #判断歌曲是否在播放或者暂停状态 try: terminate(self.process1.pid) #终结歌曲进程 except: pass #self.process1.join() self.song=[] self.process1=[] self.now_time=-1 self.start_time=-1 self.excursion_time=0 self.length=-1 self.busy=0 else: assert False,"歌曲不在播放或暂停状态" def pause(self): #暂停播放 if self.busy==1: #判断歌曲是否在播放状态 self.get_play_time() #获得当前时间 p=psutil.Process(self.process1.pid) suspend(p) #self.process1.terminate() #终结歌曲进程 self.busy=2 else: assert False,"无歌曲正在播放" def unpause(self): #继续暂停的播放 if self.busy==2: #判断歌曲是否在播放状态 self.busy=3 p=psutil.Process(self.process1.pid) resume(p) self.excursion_time=self.now_time #设置偏移时间归零 self.start_time=time.time() self.busy=1 #self.play(start=self.now_time) else: assert False,"歌曲不在暂停状态" ''' if __name__ == '__main__': music=all_music() music.load("下一站天后 - Twins.mp3") '''
from tkinter import * from PIL import Image, ImageTk import tkinter.font as tkFont from tkinter import ttk def color(color_255): #将RGB转换成16进制并以字符串格式输出 color_16=0x0 color_16=color_16+0x10000*(color_255[0]) color_16=color_16+0x100*(color_255[1]) color_16=color_16+0x1*(color_255[2]) if color_16>0xFFFFF: return '#%0x'%color_16 elif color_16>0xFFFF: return '#0%0x'%color_16 elif color_16>0xFFF: return '#00%0x'%color_16 elif color_16>0xFF: return '#000%0x'%color_16 elif color_16>0xF: return '#0000%0x'%color_16 else: return '#00000%0x'%color_16 openfiles=[] openpaths=[] next_musics=[] stop=[] class show(): #show类 def __init__(self): #主窗口 self.mouse_left_click=0#鼠标左键点击状态 self.set_time=0 self.flag_replay=0 self.win = Tk() self.win.title(u"我的音乐") self.win.iconphoto(True, PhotoImage(file='/home/xiaobai/Desktop/my_music/My_Music_tk.png')) self.frame= Frame (self.win, relief=RAISED, bg=color([135,206,250]),\ borderwidth=2,heigh=600,width=1280,cursor='arrow') self.frame.pack(side=TOP, fill=BOTH, ipadx=0, ipady=0, expand=1) #音乐列表frame self.frame2= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\ borderwidth=2,cursor='arrow') self.frame2.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1) self.frame21= Frame (self.frame2,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame21.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=1) self.frame22= Frame (self.frame2,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame22.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1) #按钮frame self.frame1= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\ borderwidth=2,cursor='arrow') self.frame1.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1) #歌词frame self.frame3= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\ borderwidth=2,cursor='arrow') self.frame3.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=0) #按钮 ft = tkFont.Font(family=u"宋体", size=15, weight=tkFont.BOLD) Button (self.frame1,font=ft,bg=color([135,206,250])\ ,activebackground="white",\ text=u"暂停",command =self.pause)\ .pack (side=LEFT, padx=13, pady=13) Button (self.frame1,font=ft,bg=color([135,206,250])\ ,activebackground="white",\ text=u"播放",command =self.play)\ .pack (side=LEFT, padx=13, pady=13) Button (self.frame1,font=ft,bg=color([135,206,250])\ ,activebackground="white",\ text=u"重新播放",command =self.replay)\ .pack (side=LEFT, padx=13, pady=13) Button (self.frame1,font=ft,bg=color([135,206,250])\ ,activebackground="white",\ text=u"下一首",command =self.next_music)\ .pack (side=LEFT, padx=13, pady=13) self.frame11= Frame (self.frame1,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame11.pack(side=LEFT,fill=Y,ipadx=20,ipady=0,expand=0) Button (self.frame1,font=ft,bg=color([59,210,61])\ ,activebackground="white",\ text=u"清空列表",command =self.stop)\ .pack (side=LEFT, padx=13, pady=13) Button (self.frame1,font=ft,bg=color([242,203,46])\ ,activebackground="white",\ text=u"打开路径",command =self.openpath)\ .pack (side=LEFT, padx=13, pady=13) Button (self.frame1,font=ft,bg=color([242,169,0])\ ,activebackground="white",\ text=u"打开文件",command =self.openfile)\ .pack (side=LEFT, padx=13, pady=13) #一些文本显示 #显示“播放列表”文本 ft = tkFont.Font(family=u"宋体", size=20, weight=tkFont.BOLD) self.frame221= Frame (self.frame22,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame221.pack(side=LEFT) Label(self.frame221,font=ft,\ text=u"播",bg=color([135,206,250])).pack(anchor='w') Label(self.frame221,font=ft,\ text=u"放",bg=color([135,206,250])).pack(anchor='w') Label(self.frame221,font=ft,\ text=u"列",bg=color([135,206,250])).pack(anchor='w') Label(self.frame221,font=ft,\ text=u"表",bg=color([135,206,250])).pack(anchor='w') #显示“倍速”文本 ft = tkFont.Font(family=u"宋体", size=10, weight=tkFont.BOLD) self.frame222= Frame (self.frame22,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame222.pack(anchor='w') Label_b=Label(self.frame222,font=ft,\ text=u" 倍速",bg=color([135,206,250])) Label_b.pack(side=LEFT) #倍速设置 self.set_comvalue=StringVar()#窗体自带的文本,新建一个值 self.set_templist=ttk.Combobox(self.frame222,font=ft,\ textvariable=self.set_comvalue,\ state='readonly',\ width=3) #初始化 self.set_templist["values"]=("0.8","0.9","1","1.2","1.4")#播放速度,可自行设置 self.set_templist.current(2) #选择第一个 self.set_templist['state'] = 'readonly'#只读 self.set_templist.bind("<<ComboboxSelected>>",self.music_speed) #绑定事件,(下拉列表框被选中时,绑定go()函数) self.set_templist.pack(side=LEFT) #列表 #音乐列表 ft = tkFont.Font(family=u"宋体", size=15, weight=tkFont.BOLD) self.list_music1=Listbox(self.frame22,bg=color([255,255,255]),\ cursor='plus',font=ft,\ fg=color([0,0,0]),height=5,width=40) self.list_music1.pack(side=LEFT, padx=13, pady=13) WAY_SET = [("单曲循环", 1),("列表播放", 2),("列表循环", 3),("随机播放", 4)] self.play_way = IntVar() self.play_way.set(2) for way, num in WAY_SET: Radiobutton(self.frame22, text=way, variable=self.play_way,\ indicatoron=False, value=num,\ font=ft,bg=color([135,206,250]),\ activebackground=color([255,192,203]),\ cursor='circle',selectcolor=color([192,192,192]),\ ).pack(anchor="w") #当前时间 self.now_time_text = StringVar() self.now_time_text.set("0"+":"+"00") ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD) Label(self.frame21,font=ft,textvariable=self.now_time_text,\ bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5) #歌曲进度 self.music_time_scale_length=600 ft = tkFont.Font(family=u"宋体", size=15, weight=tkFont.BOLD) self.frame211= Frame (self.frame21,relief=RAISED, \ bg=color([135,206,250]),\ borderwidth=0) self.frame211.pack(side=LEFT) self.music_time_scale=Scale(self.frame211,from_=0, to=180000, \ length=self.music_time_scale_length, cursor="circle",\ orient="horizontal",\ activebackground=color([128,128,128]),\ bg=color([200,200,200]),font=ft,\ bd=0,sliderrelief="ridge",sliderlength=20,\ showvalue=False) self.music_time_scale.pack(side=LEFT,padx=5, pady=0) self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun) self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun) #总时间 self.length_text = StringVar() self.length_text.set("0"+":"+"00") ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD) Label(self.frame21,font=ft,textvariable=self.length_text,\ bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5) #歌词 self.lrc_word_length=40 ft = tkFont.Font(family=u"宋体", size=25, weight=tkFont.BOLD) self.lrc_word=Listbox(self.frame3,bg=color([255,255,255]),\ cursor='plus',font=ft,\ fg=color([0,0,0]),height=2,width=self.lrc_word_length) self.lrc_word.pack(side=BOTTOM,fill=Y,ipadx=0,ipady=0,expand=0) def music_speed(self,*args): #设置播放速度 speed=float(self.set_templist.get()) self.set_time=int(self.music.get_play_time()*self.music.speed/speed) self.music.set_speed(speed) self.music.stop() self.music.play(start=self.set_time) self.music_time_scale.pack_forget() #时间进度条重画 ft = tkFont.Font(family=u"宋体", size=15, weight=tkFont.BOLD) self.music_time_scale=Scale(self.frame211,from_=0, \ to=self.music.get_length(), \ length=self.music_time_scale_length, cursor="circle",\ orient="horizontal",\ activebackground=color([128,128,128]),\ bg=color([200,200,200]),font=ft,\ bd=0,sliderrelief="ridge",sliderlength=20,\ showvalue=False) self.music_time_scale.pack(side=LEFT,padx=5, pady=0) self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun) self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun) self.music_time_scale.set(self.set_time) self.set_length_and_now_time(now_time=self.set_time,music_length=self.music.get_length()) self.win.update() #强制刷新 def set_length_and_now_time(self,now_time,music_length=None):#获取歌曲长度 if music_length!=None: self.length_text.set(str(int(music_length*self.music.speed//(1000*60))).zfill(1)\ +":"+str(int(music_length*self.music.speed//1000%60)).zfill(2)) time=int(now_time*self.music.speed) self.now_time_text.set(str(time//(1000*60)).zfill(1)\ +":"+str(time//1000%60).zfill(2)) def mouse_left_click_fun(self,event):#获取鼠标左键在进度条上点击事件 state=self.music_time_scale.identify(event.x,event.y) if state!='slider': self.set_time=int(event.x/self.music_time_scale_length*self.music.get_length()) self.music_time_scale.set(self.set_time) self.win.update() #强制刷新 self.music.stop() self.music.play(start=self.set_time) self.mouse_left_click=2 print("mouse_set_time") else: self.mouse_left_click=1 print("slide_scale") #print(f"鼠标左键点击了一次坐标是:x={event.x},y={event.y}") def mouse_left_release_fun(self,event):#获取鼠标左键在进度条上释放事件 if self.mouse_left_click==1: if event.x<0: event_x=0 elif event.x>self.music_time_scale_length: event_x=self.music_time_scale_length else: event_x=event.x self.set_time=int(event_x/self.music_time_scale_length*self.music.get_length()) self.music_time_scale.set(self.set_time) self.win.update() #强制刷新 self.music.stop() self.music.play(start=self.set_time) print("slide_scale_set_time") self.mouse_left_click=0 #print(f"鼠标左键释放坐标是:x={event.x},y={event.y}") def get_music(self,music,openfile,openpath,next_music,stop):#获取各种函数 self.music=music global openfiles openfiles=openfile global openpaths openpaths=openpath global next_musics next_musics=next_music global stop1 stop1=stop def get_music_list(self,path,list_music):#获取音乐列表 self.list_music1.delete(0,"end") for item in list_music: self.list_music1.insert("end", item) self.music_time_scale.pack_forget() if path: ft = tkFont.Font(family=u"宋体", size=15, weight=tkFont.BOLD) self.music_time_scale=Scale(self.frame211,from_=0, \ to=self.music.get_length(), \ length=self.music_time_scale_length, cursor="circle",\ orient="horizontal",\ activebackground=color([128,128,128]),\ bg=color([200,200,200]),font=ft,\ bd=0,sliderrelief="ridge",sliderlength=20,\ showvalue=False) self.music_time_scale.pack(side=LEFT,padx=5, pady=0) self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun) self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun) self.set_length_and_now_time(now_time=self.set_time,music_length=self.music.get_length()) def get_word(self,lrc_word):#获取歌词 self.lrc_word.delete(0,"end") length=0 if len(lrc_word)==1: for ch in lrc_word[0]: if u'\u4e00'<=ch<=u'\u9fff': length=length+2 else: length=length+1 else: for i in range(len(lrc_word)): if i: for ch in lrc_word[i]: if u'\u4e00'<=ch<=u'\u9fff': length=length+2 else: length=length+1 else: length=len(lrc_word[i])+length if length>60: length=60 if self.lrc_word_length>length*1.1 or self.lrc_word_length<length: self.lrc_word.pack_forget() self.lrc_word_length=int(length) ft = tkFont.Font(family=u"宋体", size=25, weight=tkFont.BOLD) self.lrc_word=Listbox(self.frame3,bg=color([255,255,255]),\ cursor='plus',font=ft,\ fg=color([0,0,0]),height=2,width=self.lrc_word_length) self.lrc_word.pack(side=BOTTOM,fill=Y,ipadx=0,ipady=0,expand=0) for i in range(len(lrc_word)): if i: self.lrc_word.insert("end", " "*len(lrc_word[0])+lrc_word[i]) else: self.lrc_word.insert("end", lrc_word[i]) def pause(self): #暂停 self.music.pause() print("pause") def stop(self): #停止并清空列表 self.set_time=0 stop1() print("stop") def play(self): #播放 self.music.unpause() print("play") def replay(self): #重新播放 self.set_time=0 self.music_time_scale.set(0) self.music.stop() self.music.play() print("replay") def openfile(self): #打开文件 self.set_time=0 openfiles() print("openfile") def set_times(self): #设置播放时间,现已弃用,集成在鼠标事件函数中 time=self.music_time_scale.get() print(time) self.set_time=time self.music.stop() self.music.play(start=time) print("set_time") def openpath(self): #打开路径 self.set_time=0 openpaths() print("openpath") def next_music(self): #下一首 self.set_time=0 next_musics() print("next_music") #show1=show() #mainloop()
就先到这吧,想到什么再写,有什么问题欢迎留言。