本文主要是介绍音乐盒项目,本地音乐播放器。python和Mysql数据库交互实战项目。运用pygame音乐模块,和Mysql数据库提取存储功能,以及python中的tkinter模块等内容实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
基础ui架构用的python中的tk模块
歌曲储存和提取用的Mysql数据库
歌曲播放等功能用高度python中的pgame模块
目录
软件功能介绍
登录界面
功能界面
完整代码
运行本地音乐盒需要预先准备的环境
软件功能介绍
更新日志: 1,添加了登录和注册的ui界面,不需要再在pyton后端登录啦。1.1,登录ui界面成功之后,才能进入音乐播放器界面;1.2,添加了注册功能,注册的账号和密码会添加到用户表这个数据库中,并且在表中一并加上注册的时间;1.3,对注册进行了优化,对登录界面进行了优化1.4,后端优化,注册名字和密码的格式1.5,前端增加登录和注册的提示,显示用户的操作1.6,设置当前登录注册ui界面不可随意改变1.7,添加了登录界面的背景图片1.8,优化了登录界面按钮的背景颜色1.9,优化了登录界面提示信息的背景颜色1.10,新增了登录界面的提示文字 2,优化了播放器的ui界面,2.1,前端新增了返回登录的按钮,并且后端实现了返回登录界面的功能2.2,扩充了播放歌曲的显示列表,使列表变的更加美观2.3,新增了播放列表的滚动滑条,2.3,新增了修改音量+和音量-的的按钮;并且后端实现了音量增加和减少的功能2.4,前端新增了【暂停】的按钮,并实现了后端暂停播放的功能2.5,前端新增了【继续播放】的按钮,并实现了后端继续播放的功能2.6,前端新增了【下一曲】的按钮,并实现了后端开启下一首播放的功能;2.7,前端新增了【上一曲】的按钮,并实现了后端开启上一首播放的功能;2.8,新增了【返回登录】按钮,并实现了后端返回登录界面的功能;2.9,以上功能都添加了前端文字提示,并且在后端对照用户的操作,一一给出提示。2.10,设置当前播放器ui界面不可随意改变2.11,新增了播放器的背景图片2.12,优化了播放界面的布局2.13,新增了进入播放器后的提示文字 3,优化了播放列表的显示功能3.1,播放列表的时候,导入音乐,不会在重复的导入了,永远都是导入最新的导入的歌曲;3.2,歌曲可以实现连续播放,随机播放的功能3.3,后数据库用户名添加了唯一约束,防止用户名重复,并且给出提示3.4,前端添加了单曲循环按钮,后端实现了实现了单曲循环! 好难实现!!!3.5,前端实现了列表循环按钮,后端实现了列表循环播放,这个也超级难!!! 之前实现了是卡死,终于在开辟线程解决了3.6,前端实现了列表随机循环按钮,后端实现了随机播放,这个最难最难!!!之前卡死,不能随机,随机报错,终于算法解决了,也解决了卡死3.7,前端增加了关闭列表循环和关闭随机循环按钮,后端实现了。不然循环开启,子线程就一直在,会卡死报错,所以我们手动分别杀死他们的线程 '''
登录界面
功能界面
具体见代码吧,代码中注释也比较多
完整代码
# encoding=utf-8
#创建数据库 misic_db
#直接通过第三方途径创建,当然也可以自己编写代码实现
import random
import sys
import threading
import time
import tkinter
from multiprocessing import Process
from threading import Thread
import pygame
from tkinter.filedialog import askopenfilenames
import tkinter as tk
import tkinter.messagebox
import tkinter.filedialog
from PIL import ImageTk, Image
from mutagen.mp3 import MP3
import inspect
import ctypesfrom PIL import Image as imim'''
更新日志:
1,添加了登录和注册的ui界面,不需要再在pyton后端登录啦。1.1,登录ui界面成功之后,才能进入音乐播放器界面;1.2,添加了注册功能,注册的账号和密码会添加到用户表这个数据库中,并且在表中一并加上注册的时间;1.3,对注册进行了优化,对登录界面进行了优化1.4,后端优化,注册名字和密码的格式1.5,前端增加登录和注册的提示,显示用户的操作1.6,设置当前登录注册ui界面不可随意改变1.7,添加了登录界面的背景图片1.8,优化了登录界面按钮的背景颜色1.9,优化了登录界面提示信息的背景颜色1.10,新增了登录界面的提示文字
2,优化了播放器的ui界面,2.1,前端新增了返回登录的按钮,并且后端实现了返回登录界面的功能2.2,扩充了播放歌曲的显示列表,使列表变的更加美观2.3,新增了播放列表的滚动滑条,2.3,新增了修改音量+和音量-的的按钮;并且后端实现了音量增加和减少的功能2.4,前端新增了【暂停】的按钮,并实现了后端暂停播放的功能2.5,前端新增了【继续播放】的按钮,并实现了后端继续播放的功能2.6,前端新增了【下一曲】的按钮,并实现了后端开启下一首播放的功能;2.7,前端新增了【上一曲】的按钮,并实现了后端开启上一首播放的功能;2.8,新增了【返回登录】按钮,并实现了后端返回登录界面的功能;2.9,以上功能都添加了前端文字提示,并且在后端对照用户的操作,一一给出提示。2.10,设置当前播放器ui界面不可随意改变2.11,新增了播放器的背景图片2.12,优化了播放界面的布局2.13,新增了进入播放器后的提示文字
3,优化了播放列表的显示功能3.1,播放列表的时候,导入音乐,不会在重复的导入了,永远都是导入最新的导入的歌曲;3.2,歌曲可以实现连续播放,随机播放的功能3.3,后数据库用户名添加了唯一约束,防止用户名重复,并且给出提示3.4,前端添加了单曲循环按钮,后端实现了实现了单曲循环! 好难实现!!!3.5,前端实现了列表循环按钮,后端实现了列表循环播放,这个也超级难!!! 之前实现了是卡死,终于在开辟线程解决了3.6,前端实现了列表随机循环按钮,后端实现了随机播放,这个最难最难!!!之前卡死,不能随机,随机报错,终于算法解决了,也解决了卡死3.7,前端增加了关闭列表循环和关闭随机循环按钮,后端实现了。不然循环开启,子线程就一直在,会卡死报错,所以我们手动分别杀死他们的线程
'''
#********************************************
# 代码实现
import pymysql#创建数据库:
def create_database():'''这是一个创建数据库的方法'''#获得链接a={'host':'localhost','port':3306,'user':'root','password':'*******','charset':'utf8'}con = pymysql.connect(**a)#获得游标cur = con.cursor()#创建一个数据库 写出sql语言sql = "CREATE database music_db default character set='utf8'"#执行cur.execute(sql)#关闭游标cur.close()#关闭链接con.close()
#封装数据库,里面有对数据库建立连接关闭连接,sql_dml对数据增更新删除方法,和see_sql查询方法,单条数据叫做see_one
class Dbutil:'''这是一个封装mysql的一个工具类实现了链接,获取游标,关闭游标,关闭链接对数据添加,更新,删除的操作对数据的查询操作'''#第一步,数据库的信息,放在类属性里面mysql_shuju={'host':'localhost','port':3306,'user':'****','password':'********','db':'music_db','charset':'utf8'}def __init__(self):'''初始化里面,创建链接'''#获得大哥,创建链接self.con=pymysql.connect(**Dbutil.mysql_shuju) #字典类型的传入方式#获得小弟,获得游标self.cur=self.con.cursor()def close_data(self):'''这个是关闭游标,关闭链接'''if self.cur: #判断里面时候有值self.cur.close()if self.con:self.con.close()def sql_dml(self,sql,args):'''这封装了对数据库的数据做增,更,删除等操作'''try:#执行sql语句,并把参数传递进去self.cur.execute(sql,args)except BaseException as e:print('数据执行失败,原因:',e)if self.con:self.con.rollback() #回滚操作else:self.con.commit() #如果没错错误,执行sql语句finally:self.close_data() #依次关闭游标和关闭链接def sql_dml1(self,sql,args):'''这封装了对数据库的数据做增,更,删除等操作'''try:#执行sql语句,并把参数传递进去self.cur.execute(sql,args)#获取id=self.con.insert_id()except BaseException as e:print('数据执行失败,原因:',e)if self.con:self.con.rollback() #回滚操作else:self.con.commit() #如果没错错误,执行sql语句#返回idreturn idfinally:self.close_data() #依次关闭游标和关闭链接def see_sql(self,sql,args):'''这是一个查询的操作'''try:self.cur.execute(sql,args)return self.cur.fetchall()except BaseException as e:print('程序执行失败,原因:',e)finally:self.close_data() #关闭数据def see_one(self,sql,args):'''这是一个查询返回单挑数据的操作'''try:self.cur.execute(sql,args)return self.cur.fetchone()except BaseException as e:print('程序执行失败,原因:',e)finally:self.close_data() #关闭数据
#这个是创建用户表的方法
def create_t_user():'''创建用户表'''#创建用户表 调用sql——dml方法#用户表有 id uname pwdsql='''create table t_user(id int primary key auto_increment,uname varchar(32),pwd varchar(32))'''Dbutil().sql_dml(sql,args=())
#这是一个新增用户的方法:
#这个是创建音乐表的方法
def create_t_music():'''这是一个歌曲列表'''#分析:歌曲表 需要有id 需要有歌曲名称,歌曲作者,歌曲地址sql='''create table t_music(id int primary key auto_increment,mname varchar(64),zuozhe varchar(64),tpath varchar(512))'''Dbutil().sql_dml(sql,args=())
#这个是创建用户的音乐列表的方法,也就是播放列表
def create_play_list():'''这是一个音乐播放列表'''#分析,列 有id 有用户id 和用户表的id关联 有mid 和音乐列表的id关联sql='''create table play_list(id int primary key auto_increment,u_id int,m_id int,foreign key (u_id) references t_user(id),foreign key (m_id) references t_music(id))'''Dbutil().sql_dml(sql,args=())
#创建了2个用户
def create_user():'''这个函数是创建用户的方法'''sql='''insert into t_user values(0,'wwww','123456')'''Dbutil().sql_dml(sql,args=())sql1='''insert into t_user values(0,'wwww1','123456')'''Dbutil().sql_dml(sql1,args=())
#编写一个音乐服务类 后台和数据库交互
class MusicService:def __init__(self):self.user=Nonedef login(self,uname:str,pwd:str)->bool:'''登录功能:param uname: 用户名:param pwd: 密码:return: 登录成功返回True,失败返回False'''#编写sqlsql= 'select id,uname from t_user where uname=%s and pwd=%s'#查询 id和用户名 来自 用户表 条件 用户名的值 和密码的值args=(uname,pwd)user=Dbutil().see_one(sql,args) #返回单条数据print(Dbutil().see_one(sql,args))if user:print('登录成功')#记录下用户信息self.user=userprint('用户信息:',user)print('看看时候有值',self.user[0])return Trueelse:print('登录失败')return False#导入音乐def add_muisc(self,fifes:tuple[str])->None:'''这是一个导入音乐的方法:param fifes: 音乐路径,默认是多个,里面的元素是字符串:return: None'''#编写sql语句 ,准备对我们音乐表格做数据添加sql='''insert into t_music(mname,tpath) values(%s,%s)'''for i in fifes:# ('D:/PycharmProjects/mypro01/课程笔记/2,项目-开发音乐盒/不醉不会.mp3',)# 导入音乐# ('D:/PycharmProjects/mypro01/课程笔记/2,项目-开发音乐盒/Maria - 极乐净土.ogg',)# D: / PycharmProjects / mypro01 / 课程笔记 / 项目 - 开发音乐盒 / Maria - 极乐净土.ogg# 导入音乐# ('D:/PycharmProjects/mypro01/课程笔记/2,项目-开发音乐盒/人间烟火.mp3',)print(i)a=i[i.rfind('/')+1:i.rfind('.')]print(a)#从后面往前找,找到斜杠+1和.之间的数值print(type(a)) # 从后面往前找,找到斜杠+1和.之间的数值#执行sqlargs=(a,i) #元组类型 添加到表格里面去mid=Dbutil().sql_dml1(sql,args) #执行数据库添加数据的方法 传入数据添加到音乐表格中#用户和音乐列表之间的关系#sql语言sql1='''insert into play_list(u_id,m_id) values(%s,%s)'''#执行sql语言 #u_id 等于我们用户名信息下的第一个值print('用户的id',self.user[0])#self.user这个值是我么通过在登录的时候,拿到的这个值,然后因为我们在一个类,所以能拿到#mid是我们通过外面的一个变量,也就是MusicService()的一个实例对象,来帮我们传递的值。我们始终调用这个实例对象#所以他args=(self.user[0],mid)Dbutil().sql_dml(sql1,args)def find_daoru(self)->list[str]:'''这是一个导入播放列表的后端查询'''sql='''select t.mname from play_list p,t_music t where p.m_id=t.id and p.u_id=%s'''args=(self.user[0],)#通过执行这个可以拿到播放列表m_list=Dbutil().see_sql(sql,args)#返回结果return m_listdef bofang_miusc(self,mname:str):'''点击播放按钮后,的后端操作'''#编写查找地址的sql语言sql='''select t.tpath from t_music t,play_list p where t.id=p.m_id and p.u_id=%s and t.mname=%s'''#把地址通过数据库的单挑查询函数,查询出来args=(self.user[0],mname)path=Dbutil().see_one(sql,args)#地址是一个元组类型,我们需要把查找下标索引值获得正确的地址print('测试ixai这个是',path[0])pygame.mixer.init() # 初始化所有引入的模块pygame.mixer.music.load(path[0]) # 载入音乐,音乐可以是 ogg、mp3 等格式pygame.mixer.music.play() # 播放载入的音乐def bofang_miusc1(self,mname:str):'''点击播放按钮后,的后端操作'''#编写查找地址的sql语言sql='''select t.tpath from t_music t,play_list p where t.id=p.m_id and p.u_id=%s and t.mname=%s'''#把地址通过数据库的单挑查询函数,查询出来args=(self.user[0],mname)path=Dbutil().see_one(sql,args)#地址是一个元组类型,我们需要把查找下标索引值获得正确的地址print('lalal',path[0])pygame.mixer.init() # 初始化所有引入的模块pygame.mixer.music.load(path[0]) # 载入音乐,音乐可以是 ogg、mp3 等格式pygame.mixer.music.play() # 播放载入的音乐audio = MP3(path[0])time.sleep(int(audio.info.length))def delect_miuxs(self,mname):#删除音乐#第一步找到要删除音乐的id 通过用户名和歌曲名字sql11='''select t.id from t_music t,play_list p where t.id=p.m_id and p.u_id=%s and t.mname=%s'''args1=(self.user[0],mname)mid=Dbutil().see_one(sql11,args1)print(mid,mid[0])#根据歌曲id 和用户id 删除播放列表12sql12='''DELETE from play_list where play_list.m_id=%s and play_list.u_id=%s;'''args=(mid[0],self.user[0])Dbutil().sql_dml(sql12,args) #执行删除这个play_list表格的数据#根据歌曲id删除歌曲表的歌曲信息sql13='''DELETE from t_music where id=%s'''args2=(mid[0],)Dbutil().sql_dml(sql13,args2)
#这里面都是后端代码服务和逻辑
# **************************************************#创造一个播放器的ui界面 16,前端-html
class Play_window:def __init__(self):self.top = tkinter.Tk() # 获取主窗口 #第一步获取主窗口# shijian1 = time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))self.top.title('凡梦音乐播放器') # 第2步,给窗口取一个名字self.top.focus_force() # 新窗口获得焦点# 第3步,设定窗口的大小(长 * 宽)self.top.geometry('1000x600')# 设定背景颜色self.top.configure(bg='gray')#设置对话框大小不可改变self.top.resizable(width=False, height=False)#设置图片背景#---------------------def get_img(filename, width, height):im = Image.open(filename).resize((width, height))im = ImageTk.PhotoImage(im)return imself.canvas_root = tk.Canvas(self.top, width=1000, height=600)im_root = get_img('133.jpg', 1200, 1100)self.canvas_root.create_image(410, 200,image=im_root)self.canvas_root.pack()#-----------------------# 按钮图片导入方法# img_open = imim.open("背景.png")# img_png = ImageTk.PhotoImage(img_open)# # ppm_button = Button(root, image=img_png)#这里是设置按钮的参数# an1 = tkinter.Button(self.top1, relief=tkinter.GROOVE, activebackground='pink', activeforeground='red',# image=img_png,# fg='purple', bg='orange', text='播 放12', width=100, height=20, font=('宋体', 50),# command=None)# an1.place(x=10, y=10, anchor='nw')# cursor = "xterm" 是书写 arrow箭头 watch 转圈# image = photo, text = compound[i], compound = compound[i]#按钮全部重写 #框架样式 点击之后按钮是粉色的 点击之后字体是红色的an1 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='播放音乐',width=8, height=2,font=('宋体', 15,'bold'), command=self.bofang)#字体颜色 bg:按钮的背景色 字体内容 大小 加粗 按钮的宽度 按钮的高度 字体的大小 响应的函数an1.place(x=10, y=10, anchor='nw')an2 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='导入音乐',width=8, height=2,font=('宋体', 15,'bold'),command=self.daoru)an2.place(x=120, y=10, anchor='nw')an3 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='删除音乐',width=8, height=2,font=('宋体', 15,'bold'),command=self.shanchu)an3.place(x=230, y=10, anchor='nw')an4 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='返回登录',width=8, height=2,font=('宋体', 15,'bold'),command=self.bangzhu)an4.place(x=340, y=10, anchor='nw')an5 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='暂停播放',width=8, height=2,font=('宋体', 15,'bold'), command=self.zhantin)an5.place(x=800, y=10, anchor='nw')an6 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='继续播放',width=8, height=2,font=('宋体', 15,'bold'), command=self.bofang1)an6.place(x=800, y=110, anchor='nw')an7 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='增加音量',width=8, height=2,font=('宋体', 15,'bold'), command=self.jia)an7.place(x=800, y=210, anchor='nw')an8 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='降低音量',width=8, height=2,font=('宋体', 15,'bold'), command=self.jian)an8.place(x=800, y=310, anchor='nw')an9 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='下 一 曲',width=8, height=2,font=('宋体', 15,'bold'), command=self.xiayiqu)an9.place(x=800, y=410, anchor='nw')an10 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='pink',text='上 一 曲',width=8, height=2,font=('宋体', 15,'bold'), command=self.shangyiqu)an10.place(x=800, y=510, anchor='nw')an11 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='gold',text='随机播放',width=8, height=2,font=('宋体', 10,'bold'), command=self.suijiboafang)an11.place(x=620, y=380, anchor='nw')an12 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='gold',text='顺序播放',width=8, height=2,font=('宋体', 10,'bold'),command=self.shunxubofang)an12.place(x=620, y=500, anchor='nw')an13 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='gold',text='单曲循环',width=8, height=2,font=('宋体', 10,'bold'), command=self.danqubofang)an13.place(x=450, y=310, anchor='nw')an14 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='gold',text='顺序关闭',width=8, height=2,font=('宋体', 10,'bold'), command=self.guanbi)an14.place(x=620, y=540, anchor='nw')an15 = tkinter.Button(self.top,relief=tkinter.GROOVE,activebackground = 'pink', activeforeground = 'red',fg='purple', bg='gold',text='随机关闭',width=8, height=2,font=('宋体', 10,'bold'),command=self.guanbi1)an15.place(x=620, y=420, anchor='nw')# 增加播放列表的对话框self.listbox = tkinter.Listbox(self.top, bg='pink', font=("宋体", 20,'bold'), width=28,height=10)self.listbox.place(x=5, y=80, anchor='nw')### 第7步,创建并放置一个多行文本框text用以显示self.t = tkinter.Text(self.top, bg='pink',font=('草体', 20,'bold'), width=40, height=10)self.t.place(x=5, y=380,anchor='nw')var='''您好,欢迎来到【凡梦播放器】,新用户-->点击【导入音乐】,点击【播放】开始播放音乐;老用户-->点击列表里面的音乐,点击【播放】开始播放音乐。'''self.t.insert('insert', var)#显示播放当前用户的播放列表self.jiza()#这里是设置的变量,每次调用都会增加的变量#这个是音乐的音量self.yinliang=0.7#这里是控制音乐列表的self.index=Noneself.shunxu=Falseself.t1=Noneself.t2 = Noneself.top.mainloop() # 主窗口循环展示 #第二步主窗口循环展示def guanbi(self):#关闭进程self.t.delete(1.0, 'end') # 清空显示对话框stop_thread(self.t1)pygame.mixer.init()pygame.mixer.music.pause()print("线程都被杀死了")var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚才中止 顺序循环播放
当前状态下,结束循环,下次开启请在点击歌曲播放'''# 通过传递过来的这个值,去查找名字 完成播放self.t.insert('insert', var)def guanbi1(self):# 关闭进程self.t.delete(1.0, 'end') # 清空显示对话框stop_thread(self.t2)pygame.mixer.init()pygame.mixer.music.pause()print("线程都被杀死了")var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚才中止 随机循环播放
当前状态下,结束循环,下次开启请在点击歌曲播放
---
'''# 通过传递过来的这个值,去查找名字 完成播放self.t.insert('insert', var)def danqubofang(self): #Play_window().danqubofang(self)print('您点击了单曲播放')self.t.delete(1.0, 'end') # 清空显示对话框# 编写查找地址的sql语言us=ms.user[0]# 获取当前列表中选中的音乐self.index = int(self.listbox.curselection()[0])mnane=self.listbox.get(self.index)print(self.index,type(self.index),type(mnane),mnane,111111)# print('这是在歌曲中查看歌曲的名字',mnane)# ms.bofang_miusc(mnane)sql = '''select t.tpath from t_music t,play_list p where t.id=p.m_id and p.u_id=%s and t.mname=%s'''# 把地址通过数据库的单挑查询函数,查询出来args=(us,mnane)path = Dbutil().see_one(sql, args)print(path[0])# 地址是一个元组类型,我们需要把查找下标索引值获得正确的地址audio = MP3(path[0])pygame.mixer.init() # 初始化所有引入的模块pygame.mixer.music.load(path[0]) # 载入音乐,音乐可以是 ogg、mp3 等格式pygame.mixer.music.play(-1) # 播放载入的音乐 #循环播放var = \f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【单曲播放】
你当前播放的歌曲中名字是:【{mnane}】
位于播放列表中第:【{self.index + 1}】首歌
【{mnane}】单曲循环中……'''# 通过传递过来的这个值,去查找名字 完成播放self.t.insert('insert', var)def shunxubofang(self):print('您点击了顺序播放')#当歌曲播放完毕之后,自动切歌:# 开辟线程 # #设置一下,当主进程关闭,子线程自动关闭self.t1=threading.Thread(target=self.zidong1,daemon=True)self.t1.start() #开启线程def zidong1(self):print('看看子线程有无开启')m_list = ms.find_daoru()while 1:for i in m_list:print(i[0]) #i【0】 是歌曲的名字#这个是歌曲的播放时间#找到当前歌曲的播放时间#通过歌曲名字找到歌曲播放的地址sql = '''select t.tpath from t_music t,play_list p where t.id=p.m_id and t.mname=%s'''# 把地址通过数据库的单挑查询函数,查询出来args = (i[0],)path = Dbutil().see_one(sql, args)#通过歌曲名字,拿到歌曲的播放地址audio = MP3(path[0]) #n是播放地址print('当前歌曲的地址是:',path[0])print('当前歌曲的播放时长是;',int(audio.info.length))#通过歌曲的播放地址,获取到歌曲的播放时长# #循环播放当前列表的歌曲ms.bofang_miusc(i[0])print('当前播放的歌曲是:',i[0])#每首歌曲依次播放,然后等待歌曲播放完毕,进入下一个首播放self.t.delete(1.0, 'end') # 清空显示对话框var = \f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。现在是列表循环播放,当前播放的歌曲是:【{i[0]}】'''self.t.insert('insert', var)time.sleep(int(audio.info.length))def suijiboafang(self):print('您点击了随机播放')self.t2=threading.Thread(target=self.zidong2,daemon=True)self.t2.start() #开启线程def zidong2(self):print('自动播放的线程开启')#等待这个歌曲播放完毕,然后自动切换到下一曲self.t.delete(1.0, 'end') # 清空显示对话框var = \f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【随机播放】'''self.t.insert('insert', var)while 1:#调用下面封装好的函数 死循环去实现吧 除非我们手动杀死这个子线程self.fen1()def fen1(self):# self.t.delete(1.0, 'end') # 清空显示对话框m_list = ms.find_daoru()self.index = 0 + random.randint(0, (len(m_list)-1))print('当前歌曲的下标内部2', self.index)self.mnane = self.listbox.get(str(self.index))ms.bofang_miusc1(self.mnane)def xiayiqu(self):print('你点击了下一曲')self.t.delete(1.0, 'end') #清空显示对话框#增加,每次点击一下增加一个索引值#找到播放列表m_list = ms.find_daoru()#找到播放列表的长度# print(m_list,type(len(m_list)),type(m_list))#当索引值小于长度-1的时候,就可以增加if self.index<(len(m_list)-1):#当前歌曲的索引小于列表长度减1的时候,就可以直接+1self.index=self.index+1print(self.index,11111)#根据索引找到名字self.mnane=self.listbox.get(str(self.index))# print('这是在歌曲中查看歌曲的名字', self.mnane, self.index)var=\f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。你刚刚点击了【下一曲】你当前播放的歌曲中名字是:【{self.mnane}】位于播放列表中第:【{self.index+1}】首歌'''#通过传递过来的这个值,去查找名字 完成播放ms.bofang_miusc(self.mnane)self.t.insert('insert', var)else:self.index=0# print('这是在歌曲中查看歌曲的名字', self.mnane, self.index)var =\f'''您好,欢迎使用【凡梦音乐播放器】,这是凡梦学习python以来第二个用来练手的软件。你刚刚点击了【下一曲】你当前播放的歌曲中名字是: 【{self.mnane}】位于播放列表中第:【{self.index+1}】首歌'''ms.bofang_miusc(self.mnane)self.t.insert('insert', var)def shangyiqu(self):print('你点击了上一曲')self.t.delete(1.0, 'end') # 清空显示对话框#增加,每次点击一下减少一个索引值m_list = ms.find_daoru()if self.index>0:self.index=self.index-1print(self.index,11111)self.mnane=self.listbox.get(str(self.index))# print('这是在歌曲中查看歌曲的名字',self.mnane,self.index)var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【上一曲】
你当前播放的歌曲中名字是:【{self.mnane}】
位于播放列表中第:【{self.index+1}】首歌'''ms.bofang_miusc(self.mnane)self.t.insert('insert', var)else:self.index=(len(m_list)-1)self.mnane=self.listbox.get(str(self.index))# print('这是在歌曲中查看歌曲的名字',self.mnane,self.index)var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【上一曲】
你当前播放的歌曲中名字是:【{self.mnane}】
位于播放列表中第:【{self.index+1}】首歌'''ms.bofang_miusc(self.mnane)self.t.insert('insert', var)def bofang1(self):print('继续播放')self.t.delete(1.0, 'end') # 清空显示对话框pygame.mixer.init()pygame.mixer.music.unpause() #继续播放当前的音乐var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【继续播放】按钮,歌曲为您播放'''self.t.insert('insert', var)def zhantin(self): #暂停播放print('暂停了音乐')self.t.delete(1.0, 'end') # 清空显示对话框pygame.mixer.init()pygame.mixer.music.pause() #暂停当前的音乐var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【暂停播放】按钮,歌曲开启暂停,点击【继续播放】按钮可继续播放'''self.t.insert('insert', var)def jian(self):print('音量减少了一下')self.t.delete(1.0, 'end') # 清空显示对话框pygame.mixer.init()self.yinliang = self.yinliang - 0.1if self.yinliang<0:self.yinliang=0pygame.mixer.music.set_volume(self.yinliang) # 设置音量print('当前音量',self.yinliang)var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【降低音量】按钮,当前音量{self.yinliang:.1f}'''self.t.insert('insert', var)def jia(self):print('音量增加了一下')self.t.delete(1.0, 'end') # 清空显示对话框pygame.mixer.init()self.yinliang = self.yinliang +0.1if self.yinliang>2.5:self.yinliang=2.5pygame.mixer.music.set_volume(self.yinliang) # 设置音量print('当前音量',self.yinliang)var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【增加音量】按钮,当前音量{self.yinliang:.1f}'''self.t.insert('insert', var) #浮点数的格式化 显示1位小数点#播放音乐的函数def bofang(self):print('播放音乐')self.t.delete(1.0, 'end') # 清空显示对话框# 获取当前列表中选中的音乐self.index = int(self.listbox.curselection()[0])index=self.listbox.curselection()mnane=self.listbox.get(index)print(index,type(index),type(mnane),mnane,111111)# print('这是在歌曲中查看歌曲的名字',mnane)ms.bofang_miusc(mnane)var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。你刚刚点击了【播放音乐】按钮,
当前播放的音乐【{mnane}】,位于歌曲列表第【{index[0]+1}】首'''self.t.insert('insert', var)#导入音乐的函数 后端def daoru(self): #这是一个事件函数,必须传入参数eventprint('导入音乐')self.t.delete(1.0, 'end') # 清空显示对话框#设置导入音乐的格式filenames=askopenfilenames(filetypes=[('mp3','.mp3'),('ogg','.ogg')])print(filenames)#调入后端我们创建列表的类ms.add_muisc(filenames)m_list = ms.find_daoru()# 打印出来看看长啥样# print(m_list)# 把这个列表显示在我们前端界面上 ,我们永远这是添加最后一首歌就完事儿了self.listbox.delete(0, tkinter.END)for i in m_list:self.listbox.insert(0, i[0])var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【导入音乐】按钮,
当前导入的音乐是【{m_list[-1][0]}】'''self.t.insert('insert', var)def jiza(self):'''这个是加载播放列表'''#通过我们查询的代码 获得属于当前用户的音乐播放列表m_list=ms.find_daoru()#打印出来看看长啥样# print(m_list)self.listbox.delete(0,tkinter.END)for i in m_list:#显示的时候,需要显示全部列表的内容self.listbox.insert(0,i[0])def shanchu(self):print('删除音乐')self.t.delete(1.0, 'end') # 清空显示对话框#获取当前列表中选中的音乐index=self.listbox.curselection()print(index) #显示的是当前播放列表中的下标索引值mnane=self.listbox.get(index)print(mnane,type(mnane),mnane[0],type(mnane[0]))#执行了删除之后,刷新一下列表,更新要显示的内容ms.delect_miuxs(mnane)self.jiza()#点击删除后,音乐暂停pygame.mixer.init()pygame.mixer.music.pause() #暂停当前的音乐var = \
f'''您好,欢迎实用【凡梦音乐播放器】,这是【凡梦】学习python以来第二个用来练手的软件。
你刚刚点击了【删除音乐】按钮,
当前删除的音乐是【{mnane}】'''self.t.insert('insert', var)#帮助一下的函数def bangzhu(self):# 设置tkinter框架的几何形状print('返回登录')a = tkinter.messagebox.askokcancel('提示', '是否返回登录界面 ') # True和false提示框 确定和取消if a:#音乐初始化pygame.mixer.init()#停止播放音乐pygame.mixer.music.stop()#关闭当前窗口self.top.destroy()#进入登录界面return Denglu()# top1.destroy() # 关闭当前窗口#这个是杀死线程的工具
def _async_raise(tid, exctype):"""raises the exception, performs cleanup if needed"""tid = ctypes.c_long(tid)if not inspect.isclass(exctype):exctype = type(exctype)res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))if res == 0:raise ValueError("invalid thread id")elif res != 1:# """if it returns a number greater than one, you're in trouble,# and you should call it again with exc=NULL to revert the effect"""ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)raise SystemError("PyThreadState_SetAsyncExc failed")#杀死线程的工具
def stop_thread(thread):_async_raise(thread.ident, SystemExit)#创造一个登录和注册的ui界面
class Denglu:def __init__(self):#获取窗口self.top1 = tkinter.Tk() # 获取主窗口 #第一步获取主窗口self.top1.title('登录界面') # 第2步,给窗口取一个名字self.top1.geometry('800x450') # 设定窗口大小# 设定背景颜色self.top1.configure(bg='gray')#设置对话框大小不可改变self.top1.resizable(width=False, height=False)#设置图片为背景# 设置背景图片def get_img(filename, width, height):im = Image.open(filename).resize((width, height))im = ImageTk.PhotoImage(im)return imcanvas_root = tk.Canvas(self.top1, width=1000, height=600)im_root = get_img('133.jpg', 1000, 600)canvas_root.create_image(500, 300, image=im_root)canvas_root.pack()#--------------------------------# 创建标签l1 = tkinter.Label(self.top1,bg='gold', text='请 输 入 用 户 名:', font=('Arial', 12), width=20, height=2)l1.place(x=70, y=80, anchor='nw')l2 = tkinter.Label(self.top1, bg='gold',text='请 输 入 密 码:', font=('Arial', 12), width=20, height=2)l2.place(x=70, y=140, anchor='nw')# 创建txt输入窗口self.e1 = tkinter.Entry(self.top1, bg='pink',show=None, font=('Arial', 26))self.e1.place(x=270, y=77, anchor='nw')self.e2 = tkinter.Entry(self.top1, bg='pink',show='*', font=('Arial', 26)) #不显示用户密码self.e2.place(x=270, y=137, anchor='nw')# 这里是设置登录按钮的b1 = tkinter.Button(self.top1, fg='purple', bg='orange',font=('宋体', 15), text='登 录', width=12, height=2, command=self.get1)b1.place(x=250, y=220, anchor='nw')b1 = tkinter.Button(self.top1, fg='purple', bg='orange',font=('宋体', 15),text='注 册', width=12, height=2, command=self.get2)b1.place(x=490, y=220, anchor='nw')# 这是设置下方txt对话框提示的self.t = tkinter.Text(self.top1, bg='pink', font=('草体', 20), width=40, height=5)self.t.place(x=100, y=300, anchor='nw')var = '''您好,欢迎来到【凡梦播放器】新用户——>输入用户名和密码,点击【注册】老用户——>输入用户名和密码,点击【登录】'''self.t.insert('insert', var)self.top1.mainloop() # 主窗口循环展示 #第二步主窗口循环展示# 这个函数是验证按钮的函数def get1(self):#新增一个对话框a = tkinter.messagebox.askokcancel('提示', '是否登录 ') # True和false提示框 确定和取消if a:self.t.delete(1.0, 'end')uname = self.e1.get()pwd = self.e2.get()if ms.login(uname, pwd): # 判定用户名和密码时候登录成功# print('1')var = f'登录成功,欢迎{uname}进入我们的播放器'self.t.insert('insert', var)self.e1.delete(0, 'end')self.e2.delete(0, 'end')self.top1.destroy() #关闭当前窗口Play_window() #进入播放器ui界面else:var = f'登录失败,请输入正确的用户名和密码'self.t.insert('insert', var)self.e1.delete(0, 'end')self.e2.delete(0, 'end')def jiance(self,a):sql='''SELECT uname from t_user where uname in(%s)'''args=(a,)t1=Dbutil().see_sql(sql,args)if t1:return Trueelse:return Falsedef get2(self):#注册#新增一个对话框a = tkinter.messagebox.askokcancel('提示', '是否注册 ') # True和false提示框 确定和取消if a:self.t.delete(1.0, 'end')uname1 = self.e1.get()pwd1 = self.e2.get()if self.jiance(uname1):var = f'注册失败,用户名已经存在;'self.t.insert('insert', var)self.e1.delete(0, 'end')self.e2.delete(0, 'end')elif len(uname1) > 3 and len(pwd1) > 3 :sql = '''insert into t_user values(0,%s,%s,%s)'''shijian1 = time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))s1 = shijian1.replace('.', '-')args = (uname1, pwd1, s1)# 把数据添加到数据表里面去Dbutil().sql_dml(sql, args)var = f'注册成功,请记住你的用户名和密码,你注册的用户名是【{uname1}】'self.t.insert('insert', var)self.e1.delete(0, 'end')self.e2.delete(0, 'end')# 数据库增加数据的语句else:var = f'注册失败,请输入正确的用户名和密码'self.t.insert('insert', var)self.e1.delete(0, 'end')self.e2.delete(0, 'end')if __name__ == '__main__':#这是后端逻辑,和数据库的交互###############################################################这里面的代码都是实现了后台的逻辑,和数据库的交互#调用创建数据库的方法,实现创建# create_database() #创建成功之后,我们注释掉#创建用户表# create_t_user() #创建成功之后,我们注释掉#创建音乐列表# create_t_music() #创建成功之后,我们注释掉#创建播放列表# create_play_list() #创建成功之后,我们注释掉#创建用户,一口气创建2个用户# create_user() #创建成功之后,我们注释掉#测试时候能登录成功MusicService().login('wwww','123456')#############################################################先创建一个变量 ,这个变量是作为一个媒介去传递各种值的ms = MusicService()Denglu()
运行本地音乐盒需要预先准备的环境
测试以上代码
1,需要安装python环境,以及该代码用到的库
2,需要安装Mysql数据库,并且按照代码注释的顺序,建立本地数据库,和建立几个用来存储数据的表格。
3,代码对连接数据库的账号和密码做了处理,请自行修改
4,歌曲自行准备,本音乐盒支持mp3和ogg格式,也可以修改里面导入音乐的类型的代码,以支持更多格式。
这篇关于音乐盒项目,本地音乐播放器。python和Mysql数据库交互实战项目。运用pygame音乐模块,和Mysql数据库提取存储功能,以及python中的tkinter模块等内容实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!