Python-简易音乐播放器制作

因为简书中的代码块比较难操作,所以大家既可看下方的源代码,也可点击知乎的链接,跳转后阅读!

Python-简易音乐播放器制作 - Lonelyroots的文章 - 知乎
https://zhuanlan.zhihu.com/p/393500129

该播放器需要使用到pycharm、MySQL8.0和navicat软件的使用。下方为播放器源代码!有什么不懂的欢迎在评论区留言!

'''play.py'''
from MyService import MyService
from tkinter.filedialog import askopenfilenames
import tkinter

class PlayWindow:       #创建一个窗口类
    def __init__(self,myService):       #初始化myService,这里的myService即为底下不作为脚本直接执行的使用方法中传进的参数myservice
        self.myService=myService        #实例属性

    def playMusic(self,even):       # 为给按钮添加事件创建的方法
        """播放音乐的方法"""
        print("点击了音乐播放按钮")
        """获取播放的音乐"""
        index = self.listbox.curselection()
        music_name = self.listbox.get(index)
        """调用播放方法进行播放音乐"""
        self.myService.play_music(music_name)

    def impMusic(self,even):
        """导入音乐的方法"""
        print("点击了导入音乐按钮")
        """打开磁盘选择音乐"""      # 导入模块askopenfilenames
        files = askopenfilenames(filetype=(['mp3','*.mp3'],))      #打开磁盘后,只能选择的文件名后缀为一个或多个.mp3,得到结果files
        """导入音乐,将选择的音乐保存到数据库,调用MyService里的add_music方法"""
        self.myService.add_music(files)     #调用MyService类里的add_music方法,因为PlayWindow下myService里初始化了,
        self.flush_list()

    def deleteMusic(self,even):
        """删除音乐的方法"""
        print("点击了删除音乐按钮")
        '''获取删除音乐的名称'''
        index = self.listbox.curselection()     # curselection可以获取到删除的音乐下标
        music_name = self.listbox.get(index)     # 用get()方法根据下标获取音乐名
        print(music_name)
        '''调用删除音乐的方法'''
        self.myService.delete_music(music_name)
        '''刷新列表'''
        self.flush_list()

    def flush_list(self):
        """刷新当前用户音乐列表的方法"""
        '''清空列表'''
        self.listbox.delete(0,tkinter.END)      #将第0个到最后一个全部清空
        '''查询该用户的所有音乐列表'''
        music_list = self.myService.findListByUser()
        if music_list:
            for m in music_list:
                self.listbox.insert(tkinter.END,m)      # listbox(插入的索引号,插入的字符串)先加入放于下方,后加入的放于上方

    def showWindow(self):
        """展示窗口的方法"""
        '''显示窗口'''
        top = tkinter.Tk()
        '''添加按钮'''
        play_button=tkinter.Button(top,text='播放')
        imp_button=tkinter.Button(top,text='导入音乐')
        delete_button=tkinter.Button(top,text='删除')
        '''布局按钮'''
        play_button.grid(row=0,column=0,padx=5,pady=5)      #将播放按钮放在第一行,第一列,padx按钮在x轴方向上的内边距(padding),是指按钮的内容与按钮边缘的距离,pady按钮在y轴方向上的内边距(padding)
        imp_button.grid(row=0,column=2,padx=5,pady=5)
        delete_button.grid(row=0, column=4, padx=5, pady=5)
        '''添加下方歌曲列表'''
        self.listbox=tkinter.Listbox(top)       #tkinter的组件listbox
        self.listbox.grid(row=1,column=0,padx=5,pady=5,columnspan=6)
        """给按钮添加事件"""
        play_button.bind("<ButtonRelease-1>",self.playMusic)
        imp_button.bind("<ButtonRelease-1>",self.impMusic)
        delete_button.bind("<ButtonRelease-1>", self.deleteMusic)
        '''添加音乐列表(一登录成功就有)'''
        self.flush_list()
        top.mainloop()

if __name__ == '__main__':      #该处的文件
    # 向控制台输入
    uname = input("请输入用户名:")
    password = input("请输入密码:")
    myservice = MyService()       #创建一个实例对象
    if myservice.login(uname,password):     #调用login登录方法,返回True,False
        print("登录成功")
        playwindow=PlayWindow(myservice)     #创建一个实例对象,PlayWindow是类,把参数往里传,在PlayWindow里的构造函数方法中初始化,在该类里就可以使用
        playwindow.showWindow()     #调用PlayWindow里的showWindow方法
    else:
        print("登录失败")
'''MyService.py'''
from dbUtil import Mydb     #导入dbUtil里的Mydb类
import pygame
class MyService:        #创建一个类
    def __init__(self):
        self.user=None      # 添加属性,一开始是None

    def login(self,uname,password):
        """创建登录方法"""
        sql = "select * from t_user where uname = %s and password = %s"     # 查询t_user表里的uname和password
        user = Mydb().query_one(sql,uname,password)      #直接调用query_one()方法
        if user:        # 如果查询到user有值
            self.user=user      # 给user赋值
            return True     #返回True
        else:       # 若user没有值
            return False        #返回False

    def add_music(self,files):
        """将音乐添加到数据库的方法"""
        for f in files:
            '''切片'''
            start = f.rfind('/')+1
            end = f.rfind('.mp3')
            music_name = f[start:end]
            '''根据歌名查询数据库是否有该首歌'''
            sql = "select * from t_music where music_name=%s"
            music = Mydb().query_one(sql,music_name)        #调用dbUtil里的类方法query_one
            if music:      # 如果查询到有这首歌
                ''' 查询关联表t_list,该用户是否添加了这首歌 '''
                sql = "select * from t_list where mid=%s and uid=%s"
                t_list = Mydb().query_one(sql,music[0],self.user[0])
                if not t_list:
                    sql = "insert into t_list(mid,uid) values(%s,%s)"
                    Mydb().exeDML(sql,music[0],self.user[0])
            else:
                '''将音乐名及其路径保存到t_music表'''
                sql = "insert into t_music(music_name,path) values(%s,%s)"
                mid = Mydb().exeDML(sql,music_name,f)     #调用Mydb类中的exeDML方法,返回id 赋值给mid
                '''用户选择的音乐保存到t_list表'''
                sql = "insert into t_list(mid,uid) values(%s,%s)"
                Mydb().exeDML(sql,mid,self.user[0])     # self.user有值的第一个字段即uid

    def findListByUser(self):
        """查询用户的音乐列表的方法"""
        sql = "select music_name from t_music m,t_list t where m.id=t.mid and t.uid=%s"
        return Mydb().query_all(sql,self.user[0])       # 返回用户已添加的音乐名

    def delete_music(self,music_name):
        """删除音乐名的方法"""
        '''根据音乐名称查询音乐id'''
        sql = "select id from t_music where music_name=%s"
        mid = Mydb().query_one(sql,music_name)
        '''删除关联表中的数据t_list'''
        sql = "delete from t_list where uid=%s and mid=%s"
        Mydb().exeDML(sql,self.user[0],mid[0])

    def play_music(self,music_name):
        """播放音乐方法"""
        '''根据音乐名称查询路径'''
        sql = "select path from t_music where music_name=%s"
        path = Mydb().query_one(sql,music_name)
        pygame.mixer.init()
        pygame.mixer.music.load(path[0])     # 进行音乐路径加载
        pygame.mixer.music.play()       # 音乐播放
'''dbUtil.py'''
import pymysql

class Mydb:
    '''创建一个类属性(字典)'''
    config = {
        "host":"localhost","user":"root","password":"a3",
        "db":"music_project",
        "charset":"utf8"
    }

    def __init__(self):
        self.connection = pymysql.connect(**Mydb.config)
        self.cursor = self.connection.cursor()

    def close(self):
        if self.cursor:
            self.cursor.close()
        if self.connection:
            self.connection.close()

    # 插入 修改 删除调用
    def exeDML(self, sql, *args):  # *args可变参数
        try:
            # 执行sql
            count = self.cursor.execute(sql, args)
            id = self.connection.insert_id()        
            # 提交事务
            self.connection.commit()
            return id
        except Exception as e:
            print(e)
            if self.connection:
                self.connection.rollback()
        finally:
            self.close()

    def query_one(self, sql, *args):
        try:
            # 执行sql
            self.cursor.execute(sql, args)
            # 获取结果集
            return self.cursor.fetchone()
        except Exception as e:
            print(e)
        finally:
            self.close()

    def query_all(self, sql, *args):
        try:
            # 执行sql
            self.cursor.execute(sql, args)
            # 获取结果集
            return self.cursor.fetchall()
        except Exception as e:
            print(e)
        finally:
            self.close()

if __name__ == "__main__":
    dbutil = Mydb()
'''MySQL运行代码'''
/* 创建数据库music_project */
create database music_project;
 
/* 创建t_user表 */
create table t_user(
    id int not null primary key auto_increment,
    uname varchar(20),
    password varchar(20)
)
 
/* 创建t_music表 */
create table t_music(
    id int not null primary key auto_increment,
    music_name varchar(25),
    path varchar(255)
)
 
/* 创建t_list表 */
create table t_list(
    id int not null primary key auto_increment,
    mid int,
    uid int,
    constraint fk_list_music_id foreign key(mid) references t_music(id),       #添加外键约束
    constraint fk_list_user_id foreign key(uid) references t_user(id)      #添加外键约束
)
 
/* 插入数据 */
insert into t_user (id,uname,password) values(1,'ch',123),(2,'ls',123);

文章到这里就结束了!希望大家能多多支持!私聊我,可以问关于本文章的问题,包教包会!长时间未回,可以添加我的微信!以后每天都会发布新文章,喜欢的点点关注!其它官方平台喜欢的也可以点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去!美好生活是靠自己掌握的!一起加油!
@知乎:Lonelyroots
@CSDN:Lonelyroots°
@简书:Lonelyroots
@微博:二十三画追梦人
@微信号:Aurora-cbh
【注】:可以转载,但需要注明出处,有什么问题,在评论区留言!我会继续努力,争取一直能够让大家白嫖下去!因为是多个平台的作者,每天都要花大把时间,若在各个平台相互转载链接也请见谅!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容