音乐播放器

目录

  • 一、设计目标
  • 二、实现流程
    • 1. 数据库操作
    • 2. 后端功能实现
    • 3. 前端UI界面实现
    • 4. 程序入口
  • 三、项目收获

一、设计目标

1. 模拟网易云音乐,实现本地音乐盒
2. 功能分析

  • 登录功能
  • 窗口显示
  • 加载本地音乐
  • 建立播放列表
  • 播放音乐
  • 删除播放列表音乐
    3.设计思路
  • 前端UI页面:播放按钮、导入音乐按钮、删除按钮、音乐播放列表
  • 后端服务端:登录功能、导入音乐的功能、播放音乐的功能、删除音乐的功能
  • 为了将前端页面和后端服务更好的结合,在实际实现中,根据设计程序的目标加入一些属性或方法,来帮助程序功能更好的实现。
    例如:前端音乐列表的加载,需要在后端服务程序中添加一个从数据库中查找当前用户音乐列表的方法,然后由前端UI界面调用把查找到的音乐加入音乐列表中。
    4.数据库组件
  • 为了实现功能,需要在数据库中设计的三张表
  • 用户表:存储用户信息,用来实现登录功能
  • 音乐表:存储音乐信息(名称、歌手、资源路径),存储所有导入的音乐,用来实现寻找音乐资源进行加载、播放和删除的功能。
  • 用户播放列表:存储用户id及其对应的音乐id,且这两个值分别有另外两张表的外键约束,用来正确的显示用户对应的歌曲。

二、实现流程

1. 数据库操作

  1. 创建数据库
# 创建音乐盒数据库
CREATE DATABASE music_dbDEFAULT CHARACTER SET = 'utf8mb4';
  1. 使用数据库
USE music_db;
  1. 创建用户表
CREATE TABLE t_user(id int(11) PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32),password VARCHAR(32)
);
  1. 创建音乐表
CREATE TABLE t_music(id int(11) PRIMARY KEY AUTO_INCREMENT,title VARCHAR(32),singer VARCHAR(32),path VARCHAR(256)
);
  1. 创建用户播放列表
CREATE Table t_play_list(id int(11) PRIMARY KEY AUTO_INCREMENT,u_id int(11),m_id int(11),FOREIGN KEY(u_id) REFERENCES t_user(id),FOREIGN KEY(m_id) REFERENCES t_music(id)
);
  1. 插入用户数据
insert into t_user(username, password) values('张三','123456');

2. 后端功能实现

1.登录功能

# 导包
from tools import DBUtil # 导入工具类:进行数据库上的操作
import pygame # 用来播放音乐class MusicService:def __init__(self) -> None:self.user = Nonedef login(self,uname,pwd) -> bool:'''用户登录功能:param uname: 用户名:param pwd: 密码'''# 编写sqlsql = "select id,username from t_user where username=%s and password=%s"# 创建工具类对象db = DBUtil()# 执行查询操作res = db.query_one(sql,uname,pwd)# 判断是否登录成功if res:# print("赋值 self.user", self.user)  # 这里应该看到 self.user 被正确赋值self.user = res print("登录成功,欢迎使用")# print(self.user[0])return Trueelse:print("登录失败")return False

2.导入音乐

    def insert_music(self,files:tuple[str]) -> None:'''将导入的音乐添加到数据库'''# 编写sqlinsert_sql = "insert into t_music(title,path) values(%s,%s)"# 遍历音乐文件for file in files:# print(file)name = file[file.rfind(" ")+1:file.rfind(".")]# 创建工具类对象db = DBUtil()# 执行sqlmid = db.execute_dml_back_id(insert_sql,name,file)# 维护用户和音乐的对应关系# 创建工具类对象db = DBUtil()# 编写sqlinsert_play_list_sql = "insert into t_play_list(u_id,m_id) values(%s,%s)"# 执行sqldb.execute_dml(insert_play_list_sql,self.user[0],mid)

3.查询用户音乐列表

    def find_user_music(self) -> list[str]:'''查询用户音乐列表:return: 音乐列表'''# 编写sqlsql = "SELECT m.title from t_play_list p left join t_music m on p.m_id = m.id WHERE u_id = %s;"# 创建工具类对象db = DBUtil()# 执行sqlm_list = db.query_all(sql,self.user[0])return m_list

4.播放音乐

    def play_music(self,music_name:str) -> None:'''播放音乐:param m_name: 音乐名'''# 编写sql:根据传入的音乐名查找对应的音乐路径sql = "SELECT m.path FROM t_play_list p left join t_music m on p.m_id = m.id WHERE u_id = %s and m.title = %s;"# 执行sql:获取音乐路径path = DBUtil().query_one(sql,self.user[0],music_name)[0]# 初始化混合器pygame.mixer.init()# 加载音乐pygame.mixer.music.load(path)# 播放音乐pygame.mixer.music.play()

5.删除音乐

    def delete_music(self,music_name:str) -> None:'''删除音乐:param: music_name: 音乐名'''# 编写sql:根据传入的音乐名查找要删除的音乐idget_id_sql = "SELECT m.id from t_music m LEFT JOIN t_play_list p on m.id = p.m_id WHERE m.title = %s and p.u_id = %s;"# 执行sql:获取音乐idmusic_id = DBUtil().query_one(get_id_sql,music_name,self.user[0])[0]# 编写sql,并删除播放列表中对应的音乐delete_play_list_sql = "DELETE FROM t_play_list WHERE u_id = %s and m_id = %s;"DBUtil().execute_dml(delete_play_list_sql,self.user[0],music_id)# 编写sql,并删除音乐表中对应的音乐delete_music_sql = "DELETE FROM t_music WHERE id = %s;"DBUtil().execute_dml(delete_music_sql,music_id)

3. 前端UI界面实现

1.初始化软件窗口

# 导包
import tkinter # 引入tkinter,绘画界面
from service import MusicService # 引入服务层
from tkinter.filedialog import askopenfilenames # 引入文件选择框class PlayWindow:'''软件窗口'''def __init__(self) -> None:top = tkinter.Tk()# 创建按钮btn1 = tkinter.Button(top,text='播放')btn2 = tkinter.Button(top,text='导入音乐')btn3 = tkinter.Button(top,text='删除')# 创建播放列表self.listbox = tkinter.Listbox(top)# 设置按钮的位置btn1.grid(row=0,column=0,padx=5,pady=5)btn2.grid(row=0,column=2,padx=5,pady=5)btn3.grid(row=0,column=4,padx=5,pady=5)# 设置播放列表的位置self.listbox.grid(row=1,column=0,columnspan=5,padx=5,pady=5)# 获取用户音乐播放列表self.load_music()# 绑定按钮事件btn2.bind('<ButtonRelease-1>',self.import_music)btn1.bind('<ButtonRelease-1>',self.play_music)btn3.bind('<ButtonRelease-1>',self.delete_music)# 进入消息循环top.mainloop()

2.导入音乐按钮事件绑定的方法

    def import_music(self,event):'''导入音乐'''print('导入音乐')# 弹出文件选择框filenames = askopenfilenames(filetypes=[('mp3','*.mp3'),('flac','*.flac')])print(filenames)# 调用服务层# ms = MusicService()# 把导入的音乐插入到数据库中ms.insert_music(filenames)# 导入新音乐后刷新播放列表self.load_music()

3.加载用户音乐播放列表的方法

    def load_music(self):'''加载用户音乐列表'''# 查询当前用户播放列表music_list = ms.find_user_music()# 清空播放列表self.listbox.delete(0,tkinter.END)# 遍历列表,把音乐名添加到播放列表中for music in music_list:self.listbox.insert(0,music[0])

4.播放音乐按钮绑定的方法

    def play_music(self,event):'''播放音乐'''# 获取当前选中的音乐索引index = self.listbox.curselection()# 获取当前选中的音乐名music_name = self.listbox.get(index)# print(music_name)# 播放音乐ms.play_music(music_name)

5.删除音乐按钮绑定的方法

    def delete_music(self,event):'''删除音乐'''# 获取当前选中的音乐索引index = self.listbox.curselection()# 根据音乐索引获取音乐名music_name = self.listbox.get(index)# 调用后台服务的删除功能ms.delete_music(music_name)# 刷新播放列表self.load_music()

4. 程序入口

if __name__ == "__main__":# 输入登录信息uname = input('请输入用户名:')pwd = input('请输入密码:')# 创建服务对象ms = MusicService()if ms.login(uname,pwd):# 创建播放窗口pw = PlayWindow()

三、项目收获

  1. 一种软件设计思维:先明确要设计的软件——>分析软件各个功能并分成模块——>前端页面绘画——>根据前端页面设计与其页面相绑定的后端方法——>后端方法要与数据库交互
  2. 一个技巧:在编写不确定的代码的时候,可以使用调试模式,使用调试控制台输入代码快速获得相应的变量输出,从而快速确定要编写的代码。这样可以有效的避免多次运行才能获得正确代码的情况,这在大型软件的设计中很有用!!!
  3. 对软件设计的认知:设计和编写前端页面、根据前端页面实现功能;其中有一个重点:后端服务层的功能重点是与数据库的交互,根据数据库返回的数据进行条件判断,提取数据库的数据进行信息呈现和功能实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[leetcode]文件组合

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<vector<int>> fileCombination(int target) {vector<vector<int>> vec;vector<int> res;int sum 0, limit (target - 1) / 2; // (target - 1) / 2 等效于 target /…

Windows 11内置一键系统备份与还原 轻松替代Ghost

面对系统崩溃、恶意软件侵袭或其他不可预见因素导致的启动失败&#xff0c;Windows 7~Windows 11内置的系统映像功能能够迅速将您的系统恢复至健康状态&#xff0c;确保工作的连续性和数据的完整性。 Windows内置3种备份策略 U盘备份&#xff1a;便携且安全 打开“创建一个恢…

Ubuntu20.04突然没网的一种解决办法

本来要学一下点云地图处理&#xff0c;用octomap库&#xff0c;但是提示少了octomap-server库&#xff0c;然后通过下面命令安装的时候&#xff1a; sudo apt install ros-noetic-octomap-server 提示&#xff1a;错误:7 https://mirrors.ustc.edu.cn/ubuntu focal-security …

MWC上海展 | 创新微MinewSemi携ME54系列新品亮相Nordic展台

6月28日&#xff0c; 2024MWC上海圆满落幕&#xff0c;此次盛会吸引了来自全球124个国家及地区的近40,000名与会者。本届大会以“未来先行&#xff08;Future First&#xff09;”为主题&#xff0c;聚焦“超越5G”“人工智能经济”“数智制造”三大子主题&#xff0c;探索讨论…

溶解氧(DO)理论指南(1)

转载自梅特勒官网资料&#xff0c;仅用于学习交流&#xff0c;侵权则删&#xff01; 溶解氧理论指南 1 溶解氧(DO)原理1.1 溶解氧和分压1.2 氧气在水中的溶解度1.3 溶解氧对生物的重要性1.4 溶解氧对工业的重要性 1 溶解氧(DO)原理 氧是宇宙中第三大常见元素&#xff0c;也是…

JavaScript(6)——数据类型转换

为什么需要类型转换&#xff1f; JavaScript是弱数据类型&#xff1a;JavaScript不知道变量到底属于哪种数据类型&#xff0c;只有赋值了才清除 使用表单&#xff0c;prompt获取的数据默认为字符串类型&#xff0c;此时不能直接进行算数运算 隐式转换 某些运算符被执行时&am…

两次叛国投敌,没有祸及子孙反而家族长盛不衰的传奇

这个人就是韩国国王韩王信&#xff0c;汉朝八大异姓王之一。 第一次叛国投敌&#xff0c;发生在楚汉争霸时期。有一次他的军队被项羽包围&#xff0c;于是选择了投降。不过&#xff0c;这是权宜之计&#xff0c;不久就借机回到刘邦阵营。 第二次叛国投敌&#xff0c;发生在西…

【Linux开发】基于ALSA库实现音量调节

基于ALSA库实现音量调节 ALSA库实现音量调节1、使用alsamixer工具查看音频接口2、完整代码2.1、snd_mixer_open2.2、snd_mixer_attach、2.3、snd_mixer_selem_register2.4、snd_mixer_load2.5、snd_mixer_first_elem/snd_mixer_elem_next2.6、snd_mixer_selem_get_playback_vol…

从零开始使用 Docsify 搭建文档站点

引言 在当今的技术环境中&#xff0c;拥有一份易于访问和美观的文档是至关重要的。Docsify 是一个非常适合快速搭建文档站点的工具&#xff0c;它简单易用&#xff0c;且不需要生成静态文件。本文将带你一步步从零开始使用 Docsify 搭建一个文档站点。 1. 安装 Node.js 和 np…

【ARMv8/v9 GIC 系列 5.1 -- GIC GICD_CTRL Enable 1 of N Wakeup Function】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC Enable 1 of N Wakeup Function基本原理工作机制配置方式应用场景小结GIC Enable 1 of N Wakeup Function 在ARM GICv3(Generic Interrupt Controller第三代)规范中,引入了一个名为"Enable 1 of N Wakeup"的功能。…

(一)Docker基本介绍

部署项目的发展 传统部署适合需要最大性能和可靠性的场景&#xff0c;但在资源利用和管理方面有显著劣势。虚拟化部署提供了良好的资源利用率和隔离性&#xff0c;适用于需要灵活扩展和多租户环境的场景&#xff0c;但存在性能开销。容器部署在轻量级、可移植性和资源利用率方面…

适合金融行业的国产传输软件应该是怎样的?

对于金融行业来说&#xff0c;正常业务开展离不开文件传输场景&#xff0c;一般来说&#xff0c;金融行业常用的文件传输工具有IM通讯、邮件、自建文件传输系统、FTP应用、U盘等&#xff0c;这些传输工具可以基础实现金融机构的文件传输需求&#xff0c;但也存在如下问题&#…

google 邮件信息收集

主要介绍通过google和fofax对目标进行邮件信息收集 chrome插件 email-whatsapp-extractor link-klipper-extract-all bulk-url-opener-extension email-whatsapp-extractor 使用正则表达式&#xff0c;获取访问页面内所有的email邮箱和whatsapp号码&#xff0c;以表格的形式导…

el-table封装点击列筛选行数据功能,支持筛选,搜索,排序功能

数据少的话&#xff0c;可以前端实现&#xff0c;如果多的话&#xff0c;建议还是请求接口比较合理父组件&#xff1a; <template> <div class"home"> <!-- <img alt"Vue logo" src"../assets/logo.png"> <HelloWorld …

Hilbert编码 思路和scala 代码

需求&#xff1a; 使用Hilbert 曲线对遥感影像瓦片数据进行编码&#xff0c;获取某个区域的编码值即可 Hilbert 曲线编码方式 思路 大致可以对四个方向的数据进行归类 左下左上右上右下 这个也对应着编码的顺序 思考在不同Hilbert深度&#xff08;阶&#xff09;情况下的…

【fastadmin开发实战】经营数据自动识别录入

项目场景描述&#xff1a;每日录入各个门店的员工经营数据&#xff0c;直接从微信复制报数、系统识别录入。 解决方案&#xff1a;各个门店按照固定的汇报模板进行汇报&#xff08;如福田店有员工1、2、3、4、5号员工&#xff0c;每个员工按模板报数&#xff09; 例如&#xf…

JMH320【亲测】【御剑九歌】唯美仙侠手游御剑九歌+WIN学习手工端+视频教程+开服清档+运营后台+授权GM物品充值后台

资源介绍&#xff1a; 这也是仙梦奇缘的一个游戏 注意&#xff1a;外网14位IP或域名 ———————————————————————————————————– ps后台介绍: 1区运营后台&#xff1a;http://ip:9981/admin/admintool/ 2区运营后台&#xff1a;http://ip…

Day44:LeedCode 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费

188. 买卖股票的最佳时机 IV 给你一个整数数组 prices 和一个整数 k &#xff0c;其中 prices[i] 是某支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说&#xff0c;你最多可以买 k 次&#xff0c;卖 k 次。 注意&…

[深度学习]卷积理解

单通道卷积 看这个的可视化就很好理解了 https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md 多通道卷积 当输入有多个通道时,卷积核需要拥有相同的通道数. 假设输入有c个通道,那么卷积核的每个通道分别于相应的输入数据通道进行卷积,然后将得到的特征图对…

51单片机STC89C52RC——14.1 直流电机调速

目录 目的/效果 1&#xff1a;电机转速同步LED呼吸灯 2 通过独立按键 控制直流电机转速。 一&#xff0c;STC单片机模块 二&#xff0c;直流电机 2.1 简介 2.2 驱动电路 2.2.1 大功率器件直接驱动 2.2.2 H桥驱动 正转 反转 2.2.3 ULN2003D 引脚、电路 2.3 PWM&…