新闻详情

新闻详情

首页 / 资讯中心 / 详情

我用 Qt 写了一个音乐播放器:能播歌、能显示歌词,还能记住歌单

发布时间:2026/10/1 6:56:54来源:尧图网络
我用 Qt 写了一个音乐播放器:能播歌、能显示歌词,还能记住歌单
最近用 Qt 做了一个小项目音乐播放器。说实话它不算什么特别厉害的大工程但做完之后还挺有成就感的。因为麻雀虽小五脏俱全能添加歌曲、播放暂停、上一首下一首、调音量、拖进度条、切播放模式还能显示歌词、同步高亮甚至关掉软件再打开歌单还能从数据库里恢复回来。这篇文章就简单总结一下这个项目顺便贴几段我觉得比较典型的代码给同样在学 Qt 的朋友一个参考。一、这个播放器能干啥先列一下功能大概就是这些添加本地 MP3 文件播放、暂停、停止上一首、下一首拖动进度条跳转调节音量切换播放模式单曲播放、单曲循环、顺序播放、循环播放、随机播放显示歌曲名、歌手加载 .lrc 歌词文件并跟着播放进度高亮用 SQLite 保存歌单下次打开自动恢复清空播放列表同时清空数据库。界面是用 Qt Designer 画的主要控件有List itemplaylistWidget歌曲列表lyricsWidget歌词列表progressSlider播放进度条volumeSlider音量条一堆按钮添加、播放、暂停、停止、上一首、下一首、模式、清空。二、项目文件大概怎么分的这个项目文件不多结构也比较清楚List itemmain.cpp程序入口创建 QApplication 和主窗口musicplayer.h / musicplayer.cpp主窗口逻辑负责界面、播放控制、歌词同步、信号槽连接musicplayer.ui界面设计文件dbhelper.h / dbhelper.cpp数据库管理负责保存和读取歌单lyricthread.h / lyricthread.cpp歌词解析线程后台解析 .lrc 文件musicplayer.proqmake 工程文件里面加了 multimedia 和 sql 模块。.pro 里比较关键的是这一句QT core gui multimedia sql因为要播放音乐所以需要 multimedia要保存歌单所以需要 sql。三、几个我觉得挺有意思的点1. 用 SQLite 记住歌单以前写播放器最烦的就是每次打开都要重新添加歌曲。这次我用 SQLite 做了持久化。数据库里只建了一张表字段就一个path歌曲路径。m_db QSqlDatabase::addDatabase(“QSQLITE”);m_db.setDatabaseName(“musicdatabase.db”);if (!m_db.open()) {qDebug() “数据库打开失败:” m_db.lastError().text();return;}initTable();建表也很简单query.exec(“CREATE TABLE IF NOT EXISTS songlist(path VARCHAR(200) PRIMARY KEY)”);这里 path 是主键所以同一首歌不会重复插入。添加歌曲的时候用 INSERT OR IGNOREquery.prepare(“INSERT OR IGNORE INTO songlist(path) VALUES(?)”);query.addBindValue(path);return query.exec();这样就算用户手滑选了同一首歌也不会重复添加。2. 歌词解析放到线程里歌词文件虽然不大但为了不让界面卡顿我还是把它放到了 QThread 里。LyricThread 继承自 QThread重写 run()在里面读文件、解析时间戳和歌词。歌词格式一般是这样的[00:28.28]一生要走多远的路程解析核心代码大概是这样QStringList parts line.split(‘]’);QStringList timeParts parts[0].split(‘:’);int minutes timeParts[0].mid(1).toInt();double seconds timeParts[1].toDouble();qint64 timestamp qRound64((minutes * 60 seconds) * 1000);QString lyricText parts[1].trimmed();if (!lyricText.isEmpty()) {m_lyrics.insert(timestamp, lyricText);}这里用 QMapqint64, QString 存歌词键是毫秒时间戳值是歌词文本。QMap 会自动按时间排序后面根据播放进度找当前歌词就很方便。另外还做了编码处理先按 UTF-8 解码如果发现乱码再尝试 GBK 或 GB18030。这个在中文歌词文件里挺实用的。3. 歌词同步靠定时器歌词高亮不是播放器自动给的而是我自己用 QTimer 定时查。每 100 毫秒查一次当前播放位置然后找到对应的歌词行。connect(lyricsTimer, QTimer::timeout,this, MusicPlayer::updateLyricsOnTime);高亮逻辑大概是这样qint64 position player-position();int row ui-lyricsWidget-currentRow();QList times m_lyrics.keys();while (row times.size() - 1 position times[row 1]) {row;}while (row 0 position times[row]) {row–;}如果行号变了就高亮新行并滚动到中间QListWidgetItem *item ui-lyricsWidget-item(row);ui-lyricsWidget-setCurrentItem(item);ui-lyricsWidget-scrollToItem(item, QAbstractItemView::PositionAtCenter);4. 信号槽把控件和功能串起来Qt 的信号槽真的挺方便。这个项目里按钮、播放器、播放列表、歌词线程、定时器基本都靠信号槽连接。connect(ui-playButton, QPushButton::clicked,this, MusicPlayer::onPlay);connect(lyricThread, LyricThread::lyricsLoaded,this, MusicPlayer::onLyricsLoaded);connect(lyricsTimer, QTimer::timeout,this, MusicPlayer::updateLyricsOnTime);播放列表切换歌曲时也要更新歌名、歌手和歌词connect(playlist, QMediaPlaylist::currentMediaChanged,this, MusicPlayer::onCurrentMediaChanged);5. 添加歌曲时顺手去重添加歌曲的时候我先检查播放列表里有没有这个路径有就跳过没有才添加。playlist-addMedia(QUrl::fromLocalFile(file));ui-playlistWidget-addItem(fileInfo.fileName());dbHelper.addSong(file);数据库那边也有主键和 INSERT OR IGNORE 兜底所以重复添加这个问题基本不用担心。6. 启动时恢复歌单程序启动时从数据库里读路径然后只加载那些文件还存在的歌曲QStringList list dbHelper.getSongList();for (QString path : list) {if (QFile::exists(path)) {playlist-addMedia(QUrl::fromLocalFile(path));ui-playlistWidget-addItem(QFileInfo(path).fileName());}}这样就算有些歌被删了或者移动了也不会显示一堆无效项。四、踩过的小坑做这个项目也遇到了一些小问题比如添加重复歌曲后来在播放列表和数据库两边都做了去重拖动进度条时和播放进度更新打架用 isSliderDown() 判断用户是不是正在拖歌词文件编码乱码先 UTF-8再 GBK/GB18030歌词文件不存在线程也会发信号界面显示“未找到歌词文件”播放出错在状态栏提示不反复操作播放器避免异常。这些问题都不算特别难但解决之后确实对 Qt 的理解更实在了。五、最后来个 200 字总结这次用 Qt 做音乐播放器最大的收获不是写了多少代码而是把信号槽、数据库、多线程、定时器这些知识串起来了。播放控制靠 QMediaPlayer 和 QMediaPlaylist歌单持久化靠 SQLite歌词解析放到 QThread 里界面不卡歌词高亮用 QTimer 每 100 毫秒查一次播放位置。过程中也踩了坑比如重复添加、歌词编码、拖动进度条冲突等。虽然项目不大但麻雀虽小五脏俱全对 Qt 的理解更实在了。以后还想加封面、搜索、在线歌词让它更像一个完整播放器。#职坐标 #AI转型 #学习分享。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

深度学习电力负荷预测实战:LSTM/GRU时序模型完整解析 2026/10/1 13:22:44

深度学习电力负荷预测实战:LSTM/GRU时序模型完整解析

简介:面向课程设计与期末大作业的深度学习区域电力负荷预测项目,基于Python构建,适合机器学习初学者及需要完整项目范例的学生参考。项目覆盖数据预处理、模型构建、训练评估与结果可视化,源码结构化划分为数据加载、训练器、模型…

阅读更多 →
MFC扫雷实战:从对话框工程到GDI双缓冲与递归展开 2026/10/1 13:22:44

MFC扫雷实战:从对话框工程到GDI双缓冲与递归展开

简介:这份资源是基于MFC框架实现的扫雷游戏完整工程,面向具备一定C基础、希望借助经典案例入门Windows GUI开发或课程设计的学习者。项目将扫雷核心逻辑与MFC的窗口管理、消息映射、CDC图形绘制、资源管理及状态维护等机制结合,帮助读者理解如…

阅读更多 →
Python爬虫+数据分析+LSTM预测与机器学习可视化完整实践 2026/10/1 13:22:44

Python爬虫+数据分析+LSTM预测与机器学习可视化完整实践

简介:面向Python爬虫与数据分析学习者的完整实践项目,集成信息爬取、LSTM时序预测与机器学习分析,适合课程设计、毕业设计、项目立项演示或作为实战入门参考。压缩包共472个文件,源码以Python脚本和Jupyter Notebook为主&#xff…

阅读更多 →
用 TypeScript 类型系统实现动态参数柯里化:type-challenges 00462 Currying 2 深度解析 2026/10/1 13:22:44

用 TypeScript 类型系统实现动态参数柯里化:type-challenges 00462 Currying 2 深度解析

示例工程 【免费下载链接】type-challenges Collection of TypeScript type challenges with online judge 项目地址: https://gitcode.com/GitHub_Trending/ty/type-challenges 点击查看 免费下载 type-challenges 的第 00462 题(Currying 2&#xff0…

阅读更多 →
AnythingLLM 实战:从本地知识库到 Agent 工作区的完整搭建指南 2026/10/1 13:22:37

AnythingLLM 实战:从本地知识库到 Agent 工作区的完整搭建指南

1. 为什么我要把 AnythingLLM 当作主力工作台 第一次接触 AnythingLLM 是在一个需要把几十份内部文档变成可问答知识库的项目里。当时试过几种方案:纯提示词拼接、自己写检索脚本、用现成的云端知识库服务。纯提示词拼接上下文一长就崩,自己写检索脚本维…

阅读更多 →
Apple Pay 接入实战:从证书配置到支付令牌解密全链路 2026/10/1 13:22:37

Apple Pay 接入实战:从证书配置到支付令牌解密全链路

简介:本资源面向在SpringBoot后端集成iOS端Apple Pay的开发者,聚焦支付回调验证这一关键环节,帮助解决支付令牌解码、签名校验与交易状态确认等实际问题。压缩包共98个文件,约93KB,以70个xml配置、10个class字节码、8个…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉