Qt 项目实战 | 音乐播放器

Qt 项目实战 | 音乐播放器

  • Qt 项目实战 | 音乐播放器
    • 播放器整体架构
    • 创建播放器主界面

官方博客:https://www.yafeilinux.com/

Qt开源社区:https://www.qter.org/

参考书:《Qt 及 Qt Quick 开发实战精解》

Qt 项目实战 | 音乐播放器

开发环境:Qt Creator 3.3.0 + Qt 4.8.6

在这里插入图片描述

播放器整体架构

在这里插入图片描述

创建播放器主界面

新建 Qt Gui 应用,项目名 myPlayer,基类为 QWidget,类名为 MyWidget。

添加资源文件 myImages,前缀为空,将 images 中的所有图片都添加进去。

在这里插入图片描述

myPlayer.pro 添加代码:

QT += phonon

在 mywidget.h 添加头文件和类前置声明:

#include <phonon>class QLabel;

添加私有变量、函数:

Phonon::MediaObject *mediaObject;
QAction *playAction;
QAction *stopAction;
QAction *skipBackwardAction;
QAction *skipForwardAction;
QLabel *topLabel;
QLabel *timeLabel;void initPlayer();

添加私有槽:

private slots:void updateTime(qint64 time);void setPaused();void skipBackward();void skipForward();void openFile();void setPlaylistShown();void setLrcShown();

在 mywidget.cpp 中添加头文件:

#include <QLabel>
#include <QToolBar>
#include <QVBoxLayout>
#include <QTime>

在构造函数中添加代码:

initPlayer();

添加 initPlayer() 函数的定义:

// 初始化播放器
void MyWidget::initPlayer()
{// 设置主界面标题、图标和大小setWindowTitle(tr("音乐播放器"));setWindowIcon(QIcon(":/images/icon.png"));setMinimumSize(320, 160);setMaximumSize(320, 160);// 创建媒体图mediaObject = new Phonon::MediaObject(this);Phonon::AudioOutput* audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);Phonon::createPath(mediaObject, audioOutput);// 关联媒体对象的tick()信号来更新播放时间的显示connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime(qint64)));// 创建顶部标签,用于显示一些信息topLabel = new QLabel(tr("<a href = \" https://blog.csdn.net/ProgramNovice \"> https://blog.csdn.net/ProgramNovice </a>"));topLabel->setTextFormat(Qt::RichText);topLabel->setOpenExternalLinks(true);topLabel->setAlignment(Qt::AlignCenter);// 创建控制播放进度的滑块Phonon::SeekSlider* seekSlider = new Phonon::SeekSlider(mediaObject, this);// 创建包含播放列表图标、显示时间标签和桌面歌词图标的工具栏QToolBar* widgetBar = new QToolBar(this);// 显示播放时间的标签timeLabel = new QLabel(tr("00:00 / 00:00"), this);timeLabel->setToolTip(tr("当前时间 / 总时间"));timeLabel->setAlignment(Qt::AlignCenter);timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);// 创建图标,用于控制是否显示播放列表QAction* PLAction = new QAction(tr("PL"), this);PLAction->setShortcut(QKeySequence("F4"));PLAction->setToolTip(tr("播放列表(F4)"));connect(PLAction, SIGNAL(triggered()), this, SLOT(setPlaylistShown()));// 创建图标,用于控制是否显示桌面歌词QAction* LRCAction = new QAction(tr("LRC"), this);LRCAction->setShortcut(QKeySequence("F2"));LRCAction->setToolTip(tr("桌面歌词(F2)"));connect(LRCAction, SIGNAL(triggered()), this, SLOT(setLrcShown()));// 添加到工具栏widgetBar->addAction(PLAction);widgetBar->addSeparator();widgetBar->addWidget(timeLabel);widgetBar->addSeparator();widgetBar->addAction(LRCAction);// 创建播放控制动作工具栏QToolBar* toolBar = new QToolBar(this);// 播放动作playAction = new QAction(this);playAction->setIcon(QIcon(":/images/play.png"));playAction->setText(tr("播放(F5)"));playAction->setShortcut(QKeySequence(tr("F5")));connect(playAction, SIGNAL(triggered()), this, SLOT(setPaused()));// 停止动作stopAction = new QAction(this);stopAction->setIcon(QIcon(":/images/stop.png"));stopAction->setText(tr("停止(F6)"));stopAction->setShortcut(QKeySequence(tr("F6")));connect(stopAction, SIGNAL(triggered()), mediaObject, SLOT(stop()));// 跳转到上一首动作skipBackwardAction = new QAction(this);skipBackwardAction->setIcon(QIcon(":/images/skipBackward.png"));skipBackwardAction->setText(tr("上一首(Ctrl+Left)"));skipBackwardAction->setShortcut(QKeySequence(tr("Ctrl+Left")));connect(skipBackwardAction, SIGNAL(triggered()), this, SLOT(skipBackward()));// 跳转到下一首动作skipForwardAction = new QAction(this);skipForwardAction->setIcon(QIcon(":/images/skipForward.png"));skipForwardAction->setText(tr("下一首(Ctrl+Right)"));skipForwardAction->setShortcut(QKeySequence(tr("Ctrl+Right")));connect(skipForwardAction, SIGNAL(triggered()), this, SLOT(skipForward()));// 打开文件动作QAction* openAction = new QAction(this);openAction->setIcon(QIcon(":/images/open.png"));openAction->setText(tr("播放文件(Ctrl+O)"));openAction->setShortcut(QKeySequence(tr("Ctrl+O")));connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));// 音量控制部件Phonon::VolumeSlider* volumeSlider = new Phonon::VolumeSlider(audioOutput, this);volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);// 添加到工具栏toolBar->addAction(playAction);toolBar->addSeparator();toolBar->addAction(stopAction);toolBar->addSeparator();toolBar->addAction(skipBackwardAction);toolBar->addSeparator();toolBar->addAction(skipForwardAction);toolBar->addSeparator();toolBar->addWidget(volumeSlider);toolBar->addSeparator();toolBar->addAction(openAction);// 创建主界面布局管理器QVBoxLayout* mainLayout = new QVBoxLayout;mainLayout->addWidget(topLabel);mainLayout->addWidget(seekSlider);mainLayout->addWidget(widgetBar);mainLayout->addWidget(toolBar);setLayout(mainLayout);mediaObject->setCurrentSource(Phonon::MediaSource("../myPlayer/music.mp3"));
}

添加 updateTime(qint64 time) 槽的定义:

// 更新 timeLabel 标签显示的播放时间
void MyWidget::updateTime(qint64 time)
{qint64 totalTimeValue = mediaObject->totalTime();QTime totalTime(0, (totalTimeValue / 60000) % 60, (totalTimeValue / 1000) % 60);QTime currentTime(0, (time / 60000) % 60, (time / 1000) % 60);QString str = currentTime.toString("mm:ss") + " / " + totalTime.toString("mm:ss");timeLabel->setText(str);
}

添加 setPaused() 槽的定义:

// 播放或者暂停
void MyWidget::setPaused()
{// 如果先前处于播放状态,那么暂停播放;否则,开始播放if (mediaObject->state() == Phonon::PlayingState)mediaObject->pause();elsemediaObject->play();
}

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

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

相关文章

sqlite3.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher

问题描述 sqlite3.NotSupportedError: deterministicTrue requires SQLite 3.8.3 or higher 解决方法 A kind of solution is changing the database from sqlite3 to pysqlite3. After acticate the virtualenv, install pysqlite. pip3 install pysqlite3 pip3 install …

【Linux】vim

文章目录 一、vim是什么&#xff1f;二 、命令模式三、插入模式四、底行模式五、vim配置 一、vim是什么&#xff1f; Vim是一个强大的文本编辑器&#xff0c;它是Vi的增强版&#xff0c;支持多种语法高亮、插件扩展、多模式操作等功能。Vim有三种基本的工作模式&#xff1a;命…

self.register_buffer方法使用解析(pytorch)

self.register_buffer就是pytorch框架用来保存不更新参数的方法。 列子如下&#xff1a; self.register_buffer("position_emb", torch.randn((5, 3)))第一个参数position_emb传入一个字符串&#xff0c;表示这组参数的名字&#xff0c;第二个就是tensor形式的参数…

互联网Java工程师面试题·Spring篇·第七弹

目录 36、什么是基于 Java 的 Spring 注解配置? 给一些注解的例子. 37、什么是基于注解的容器配置? 38、怎样开启注解装配&#xff1f; 39、Required 注解 40、Autowired 注解 41、Qualifier 注解 42、在 Spring 框架中如何更有效地使用 JDBC? 43、JdbcTemplate 44…

Flink的API分层、架构与组件原理、并行度、任务执行计划

Flink的API分层 Apache Flink的API分为四个层次&#xff0c;每个层次都提供不同的抽象和功能&#xff0c;以满足不同场景下的数据处理需求。下面是这四个层次的具体介绍&#xff1a; CEP API&#xff1a;Flink API 最底层的抽象为有状态实时流处理。其抽象实现是Process Functi…

macOS电池续航工具:Endurance中文

Endurance for Mac是一款强大而实用的电池管理和优化软件&#xff0c;专为MacBook设计。通过智能调整系统设置和管理后台应用&#xff0c;它能有效延长电池续航时间&#xff0c;提升工作和娱乐效率&#xff0c;成为你在各种场合下的得力助手。 Endurance for Mac软件的功能特色…

spring中纯注解实现Advice

背景&#xff1a;课本上是注解和Xml文件混用的方式&#xff0c;研究了一下用配置类加注解和测试方法实现各种通知方式的切入。 1.首先dao的接口&#xff0c;增删改查 public interface UserDaoAspect {public void add();public void delete();public void update();public vo…

【Go 编程实践】从零到一:创建、测试并发布自己的 Go 库

为什么需要开发自己的 Go 库 在编程语言中&#xff0c;包&#xff08;Package&#xff09;和库&#xff08;Library&#xff09;是代码组织和复用的重要工具。在 Go 中&#xff0c;包是代码的基本组织单位&#xff0c;每个 Go 程序都由包构成。包的作用是帮助组织代码&#xf…

[java进阶]——方法引用改写Lambda表达式

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 &#x1f4d5;概念介绍&#xff1a; ⭐方法引用的前提条件&#xff1a; 1.引用静态方法 2.引用构造方法 ①类的构造&#xff1a; ②数组的构造&#xff1a; 3.引用本类或父类的成员方法 ①本类&#xff1…

思维训练4

题目描述1 Problem - A - Codeforces 题目分析 对于此题我们要求差值种类最大&#xff0c;故我们可以构造出相邻差值分别为1&#xff0c;2&#xff0c;3...由于n规定了最大的范围故我们增到一定的差值之后其差值必定为之前出现过的数字&#xff0c;但由于要保证数组呈递增趋势…

学习LevelDB架构的检索技术

目录 一、LevelDB介绍 二、LevelDB优化检索系统关键点分析 三、读写分离设计和内存数据管理 &#xff08;一&#xff09;内存数据管理 跳表代替B树 内存数据分为两块&#xff1a;MemTable&#xff08;可读可写&#xff09; Immutable MemTable&#xff08;只读&#xff0…

Qt Creator插件

这里以Qt Creator 4.15.2版本的源码为示例进行分析 源码结构如下&#xff0c;为了追溯其插件加载过程&#xff0c;从main.cpp入手 Qt Creator的插件目录&#xff0c;生成的插件&#xff0c;好几十个呢 Qt Creator插件的读取 int main(int argc, char **argv)中以下代码创建插…

Vue 3 相对于 Vue2,模板和组件的一些变化

目录 1&#xff0c;模板的变化1&#xff0c;v-modelvue2vue3 2&#xff0c;v-if 和 v-for3&#xff0c;keyv-forv-if 4&#xff0c;Fragment 2&#xff0c;组件的变化1&#xff0c;Teleport2&#xff0c;异步组件 1&#xff0c;模板的变化 1&#xff0c;v-model vue2 对组件…

垃圾回收系统小程序定制开发搭建攻略

在这个数字化快速发展的时代&#xff0c;垃圾回收系统的推广对于环境保护和可持续发展具有重要意义。为了更好地服务于垃圾回收行业&#xff0c;本文将分享如何使用第三方制作平台乔拓云网&#xff0c;定制开发搭建垃圾回收系统小程序。 首先&#xff0c;使用乔拓云网账号登录平…

【UE5 Cesium】actor随着视角远近来变化其本身大小

效果 步骤 1. 首先我将“DynamicPawn”设置为默认的pawn类 2. 新建一个父类为actor的蓝图&#xff0c;添加一个静态网格体组件 当事件开始运行后添加一个定时器&#xff0c;委托给一个自定义事件&#xff0c;每2s执行一次&#xff0c;该事件每2s获取一下“DynamicPawn”和acto…

html+css 通过div模拟出一个表格样式,优化多个边框导致的宽度计算问题

htmlcss 通过div模拟出一个表格样式&#xff0c;优化多个边框导致的宽度计算问题 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, i…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步&#xff1a; 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件&#xff0c;它提供了一个可视化的表格控件&#xff0c;允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

JavaEE-博客系统2(功能设计)

本部分内容&#xff1a;实现博客列表页&#xff1b;web程序问题的分析方法&#xff1b;实现博客详情页&#xff1b; 该部分的代码如下&#xff1a; WebServlet("/blog") public class BlogServlet extends HttpServlet {//Jackson ObjectMapper类(com.fasterxml.jac…

Pyhotn: Mac安装selenium没有chromedriver-114以上及chromedriver无法挪到/usr/bin目录下的问题

1.0 安装selenium 终端输入&#xff1a; pip install selenium 查看版本&#xff1a; pip show selenium2.0 安装chromedriver 查看chrome版本 网上大多数是&#xff0c;基本到114就停了。 https://registry.npmmirror.com/binary.html?pathchromedriver/ 各种搜索&#…

ros1 自定义订阅者Subscriber的编程实现

话题模型 图中&#xff0c;我们使用ROS Master管理节点。 有两个主要节点&#xff1a; Publisher&#xff0c;名为Turtle Velocity&#xff08;即海龟的速度&#xff09;Subscriber&#xff0c;即海龟仿真器节点 /turtlesim Publisher(Turtle Velocity)&#xff0c;发布Messa…