QT开发笔记(多媒体)

多媒体

多媒体(Multimedia)是多种媒体的综合,一般包括文本,声音和图像等多种媒体形式。

在计算机系统中,多媒体指组合两种或两种以上媒体的一种人机交互式信息交流和传播媒体。
使用的媒体包括文字、图片、照片、声音、动画和影片,以及程式所提供的互动功能。
Qt 的多媒体模块提供了音频、视频、录音、摄像头拍照和录像等功能。本章将介绍 Qt 多
媒体的功能和使用。

Qt 多媒体简介

Qt 从 4.4 版本开始提供的一套多媒体框架,提供多媒体回放的功能。在 Qt 4.6 中实现多媒
体播放图形界面主要依赖 phonon 框架。phonon 最初是 一个 源于 KDE 的项目,为使用音频和
视频的应用程序开发提供的一个框架。应用程序不用去管多媒体播放是通过什么实现的(如

gstreamer、xine),只需调用相应的接口就行,但这中间需要一个中转,被称为 backend。Qt 也
是通过 phonon 来实现跨平台的多媒体播放。

从 Qt5 开始,Qt 就弃用了 phonon,直接使用 Qt Multimedia 模块。我们可以 Qt Multimedia

模块来提供的类实现跨平台的多媒体播放了。使用 Qt Multimedia 就不需要中转了,但是底层还
是需要多媒体插件实现的。Qt 只是提供多媒体接口,播放多媒体实际上是通过多媒体插件实现
的,我们不需要管这些插件是什么,Qt 在不同平台使用的多媒体插件不同。本章将会介绍如何
在 Windows 和 Linux 安装多媒体插件,Mac 系统不考虑,笔者条件有限!
Qt 多媒体模块提供了很多类,主要有 QMediaPlayer,QSound、QSoundEffect、QAudioOutput、

QAudioInput、QAudioRecorder、QVideoWidget 等等。类太多了不一一作解释,可以直接复制名
字到 Qt 的帮助文档里查看该解释。可以从名称大概了解它们是什么意思,具体类的使用直接看
本章的例子。

想要在 Qt 里使用使用 Qt 多媒体模块,需要在 pro 项目文件里添加如下语句。
QT += multimedia

注意:Qt 中的音乐播放器与视频播放器需要在 Ubuntu 里安装媒体解码器才能实现播放。

 Ubuntu16 / Ubuntu18,需要安装以下插件。播放音乐需要安装 Gst 解码插件。需要在终端
输入如下指令,注意不要复制错误了,下面指令已经在 Ubuntu16/Ubuntu18 测试成功,如
果读者 Ubuntu 没有配置网络与源服务器,这些导致安装不成功与本教程无关,确实需要
读者好好打下 Ubuntu 操作的基础了!

sudo apt-get install gstreamer1.0-plugins-base gstreamer1.0-plugins-bad gstreamer1.0-plugins-good 
gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudio gstreamer1.0-libav 

 Windows 需要安装如 LAVFilters 解码器,只需要百度 LAVFilters,找到 LAVFilters 官网下载此
软件即可,当然本教程的资料会提供一份 LAVFilters 的安装包。点击页脚下方的程序下载链
接跳转到下载本教程所有资料下载地址处,在顶层目录下。

音效文件播放

播放音效文件,比如简短的提示音(按键音等),可以使用 Qt 的 QSoundEffect 和 QSound

类来播放。
Qt 的 QSoundEffect 和 QSound 类主要区别是 QSoun(d 异步方式播放)只能播放本地的 WAV

音效文件(WAV 音效文件是 PC 机上最为流行的声音文件格式,但其文件尺寸较大,多用于存
储简短的声音片段,具有低延时性,不失真的特点),QSoundEffect 不仅可以播放网络文件,也
可以播放本地音效文件,播放网络的文件一般使用到 QUrl 链接。

应用实例

本例目的:了解 QSound 类的使用。

例 13_button_sound,按钮音效测试(难度:一般)。项目路径为 Qt/2/13_button_sound。本
例大体流程,通过点击一个按钮,然后使用 QSound 来播放音效文件,模仿按键按下的声音。

项目文件 13_button_sound.pro 文件第一行添加的代码部分如下。

13_button_sound.pro 编程后的代码

1 QT += core gui multimedia 

2 

3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 

4 

5 CONFIG += c++11 

6 

7 # The following define makes your compiler emit warnings if you use 

8 # any Qt feature that has been marked deprecated (the exact warnings 

9 # depend on your compiler). Please consult the documentation of the 

10 # deprecated API in order to know how to port your code away from it. 

11 DEFINES += QT_DEPRECATED_WARNINGS 

12 

13 # You can also make your code fail to compile if it uses deprecated APIs. 

14 # In order to do so, uncomment the following line. 

15 # You can also select to disable deprecated APIs only up to a certain 
version of Qt. 

16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the 
APIs deprecated before Qt 6.0.0 

17 

18 SOURCES += \ 

19 main.cpp \ 

20 mainwindow.cpp 

21 

22 HEADERS += \ 

23 mainwindow.h 

24 

25 # Default rules for deployment. 

26 qnx: target.path = /tmp/$${TARGET}/bin 

27 else: unix:!android: target.path = /opt/$${TARGET}/bin 

28 !isEmpty(target.path): INSTALLS += target 

29 

30 RESOURCES += \ 

31 src.qrc 

在头文件“mainwindow.h”具体代码如下。

mainwindow.h 编程后的代码

 /****************************************************************** 
 Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. 
 * @projectName 13_button_sound 
 * @brief mainwindow.h 
 * @author Deng Zhimao 
 * @email 1252699831@qq.com 
 * @net www.openedv.com 
 * @date 2021-04-20 
 *******************************************************************/ 

1 #ifndef MAINWINDOW_H 

2 #define MAINWINDOW_H 

3 

4 #include <QMainWindow> 

5 #include <QSound> 

6 #include <QPushButton> 

7 

8 class MainWindow : public QMainWindow 

9 { 

10 Q_OBJECT 

11 

12 public: 

13 MainWindow(QWidget *parent = nullptr); 

14 ~MainWindow(); 

15 

16 private: 

17 /* 按钮 */ 

18 QPushButton *pushButton; 

19 

20 private slots: 

21 /* 按钮点击槽函数 */ 

22 void pushButtonClicked(); 

23 

24 }; 

25 #endif // MAINWINDOW_H 

26 

头文件里主要是声明界面使用的一个按钮,及按钮槽函数。

在源文件“mainwindow.cpp”具体代码如下。

mainwindow.cpp 编程后的代码

 /****************************************************************** 
 Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. 
 * @projectName 13_button_sound 
 * @brief mainwindow.cpp 
 * @author Deng Zhimao 
 * @email 1252699831@qq.com 
* @net www.openedv.com 
 * @date 2021-04-20 
 *******************************************************************/ 

1 #include "mainwindow.h" 

2 

3 MainWindow::MainWindow(QWidget *parent) 

4 : QMainWindow(parent) 

5 { 

6 /* 设置主窗体的位置与大小 */ 

7 this->setGeometry(0, 0, 800, 480); 

8 

9 /* 实例化按钮 */ 

10 pushButton = new QPushButton(this); 

11 

12 /* 设置按钮文本 */ 

13 pushButton->setText("按钮音效测试"); 

14 

15 /* 设置按钮的位置与大小 */ 

16 pushButton->setGeometry(340, 220, 120, 40); 

17 

18 /* 信号槽连接 */ 

19 connect(pushButton, SIGNAL(clicked()), 

20 this, SLOT(pushButtonClicked())); 

21 } 

22 

23 MainWindow::~MainWindow() 

24 { 

25 } 

26 

27 void MainWindow::pushButtonClicked() 

28 { 

29 /* 异步的方式播放 */ 

30 QSound::play(":/audio/bell.wav"); 

31 } 

第 30 行,直接使用 QSound 的静态函数 play()播放,这种播放方式是异步的,可以多次点
击按钮连续听到点击的声音。

程序运行效果

单击按钮后,可以听到播放 1 秒左右的叮咚声,用此方法来模拟单击按钮声音效果。

在这里插入图片描述

音乐播放器

QMediaPlayer 类是一个高级媒体播放类。它可以用来播放歌曲、电影和网络广播等内容。
一般用于播放 mp3 和 mp4 等等媒体文件。QMediaPlayer 类常常与 QMediaPlaylist 类一起使用。
可以很轻松的设计一个自己喜欢的音乐播放器与视频播放器。
QMediaPlayer 提供了很多信号,我们可以使用这些信号来完成音乐播放器的一系列操作,
比如媒体状态改变的信号 stateChanged(QMediaPlayer::State state),判断这个 state 的状态就可以
知道什么时候媒体暂停、播放、停止了。Qt 在媒体播放类已经提供了很多功能函数给我们使用,
像直接使用 play()函数就可以实现音乐文件的播放,前提我们需要知道媒体文件的路径。pause()

函数可以直接暂停媒体播放等等,这些都可以在 Qt 帮助文档里查看 QMediaPlayer 类的使用方
法就可以知道。不再一一列出。

应用实例

本例设计一个比较好看的音乐播放器,界面是笔者模仿网上的一个音乐播放器的界面,并
非笔者原创界面,只是笔者用 Qt 实现了网上的一个好看的音乐播放器界面。其中本例有些功能
并没有完善,比如播放模式、没有加音量控制等。这些可以由读者自由完善,比较简单。

本例目的:音乐播放器的设计与使用。

例 14_musicplayer,音乐播放器(难度:中等)。项目路径为 Qt/2/14_musicplayer。注意本
例有用到 qss 样式文件,关于如何添加资源文件与 qss 文件请参考 7.1.3 小节。音乐播放器的功
能这些都为大家所熟知,不用笔者介绍了。

项目文件 14_musicplayer.pro 文件第一行添加的代码部分如下。

14_musicplayer.pro 编程后的代码

1 QT += core gui multimedia 

2 

3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 

4 

5 CONFIG += c++11 

6 

7 # The following define makes your compiler emit warnings if you use 

8 # any Qt feature that has been marked deprecated (the exact warnings 

9 # depend on your compiler). Please consult the documentation of the 

10 # deprecated API in order to know how to port your code away from it. 

11 DEFINES += QT_DEPRECATED_WARNINGS 

12 

13 # You can also make your code fail to compile if it uses deprecated APIs. 

14 # In order to do so, uncomment the following line. 

15 # You can also select to disable deprecated APIs only up to a certain 
version of Qt. 

16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the 
APIs deprecated before Qt 6.0.0 

17 

18 SOURCES += \ 

19 main.cpp \ 

20 mainwindow.cpp 

21 

22 HEADERS += \ 

23 mainwindow.h 

24 

25 # Default rules for deployment. 

26 qnx: target.path = /tmp/$${TARGET}/bin 

27 else: unix:!android: target.path = /opt/$${TARGET}/bin 

28 !isEmpty(target.path): INSTALLS += target 

29 

30 RESOURCES += \ 

31 res.qrc 

在头文件“mainwindow.h”具体代码如下。

mainwindow.h 编程后的代码

 /****************************************************************** 
 Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. 
 * @projectName 14_musicplayer 
 * @brief mainwindow.h 
 * @author Deng Zhimao 
 * @email 1252699831@qq.com 
 * @net www.openedv.com 
 * @date 2021-04-20 
 *******************************************************************/
1 #ifndef MAINWINDOW_H 

2 #define MAINWINDOW_H 

3 

4 #include <QMainWindow> 

5 #include <QMediaPlayer> 

6 #include <QMediaPlaylist> 

7 #include <QPushButton> 

8 #include <QSlider> 

9 #include <QVBoxLayout> 

10 #include <QHBoxLayout> 

11 #include <QListWidget> 

12 #include <QLabel> 

13 #include <QSpacerItem> 

14 #include <QDebug> 

15 

16 /* 媒体信息结构体 */ 

17 struct MediaObjectInfo { 

18 /* 用于保存歌曲文件名 */ 

19 QString fileName; 

20 /* 用于保存歌曲文件路径 */ 

21 QString filePath; 

22 }; 

23 

24 class MainWindow : public QMainWindow 

25 { 

26 Q_OBJECT 

27 

28 public: 

29 MainWindow(QWidget *parent = nullptr); 

30 ~MainWindow(); 

31 

32 private: 

33 /* 媒体播放器,用于播放音乐 */ 

34 QMediaPlayer *musicPlayer; 

35 

36 /* 媒体列表 */ 

37 QMediaPlaylist *mediaPlaylist; 

38 

39 /* 音乐列表 */ 

40 QListWidget *listWidget; 

41 

42 /* 播放进度条 */ 

43 QSlider *durationSlider; 

44 

45 /* 音乐播放器按钮 */ 

46 QPushButton *pushButton[7]; 

47 

48 /* 垂直布局 */ 

49 QVBoxLayout *vBoxLayout[3]; 

50 

51 /* 水平布局 */ 

52 QHBoxLayout *hBoxLayout[4]; 

53 

54 /* 垂直容器 */ 

55 QWidget *vWidget[3]; 

56 

57 /* 水平容器 */ 

58 QWidget *hWidget[4]; 

59 

60 /* 标签文本 */ 

61 QLabel *label[4]; 

62 

63 /* 用于遮罩 */ 

64 QWidget *listMask; 

65 

66 /* 音乐布局函数 */ 

67 void musicLayout(); 

68 

69 /* 主窗体大小重设大小函数重写 */ 

70 void resizeEvent(QResizeEvent *event); 

71 

72 /* 媒体信息存储 */ 

73 QVector<MediaObjectInfo> mediaObjectInfo; 

74 

75 /* 扫描歌曲 */ 

76 void scanSongs(); 

77 

78 /* 媒体播放器类初始化 */ 

79 void mediaPlayerInit(); 

80 

81 private slots: 

82 /* 播放按钮点击 */ 

83 void btn_play_clicked(); 

84 

85 /* 下一曲按钮点击*/

86 void btn_next_clicked(); 

87 

88 /* 上一曲按钮点击 */ 

89 void btn_previous_clicked(); 

90 

91 /* 媒体状态改变 */ 

92 void mediaPlayerStateChanged(QMediaPlayer::State); 

93 

94 /* 列表单击 */ 

95 void listWidgetCliked(QListWidgetItem*); 

96 

97 /* 媒体列表项改变 */ 

98 void mediaPlaylistCurrentIndexChanged(int); 

99 

100 /* 媒体总长度改变 */ 

101 void musicPlayerDurationChanged(qint64); 

102 

103 /* 媒体播放位置改变 */ 

104 void mediaPlayerPositionChanged(qint64); 

105 

106 /* 播放进度条松开 */ 

107 void durationSliderReleased(); 

108 }; 

109 #endif // MAINWINDOW_H 

头文件里主要是声明界面所使用的元素及一些槽函数。

在源文件“mainwindow.cpp”具体代码如下。

mainwindow.cpp 编程后的代码

 /****************************************************************** 
 Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. 
 * @projectName 14_musicplayer 
 * @brief mainwindow.cpp 
 * @author Deng Zhimao 
 * @email 1252699831@qq.com 
 * @net www.openedv.com 
 * @date 2021-04-20 
 *******************************************************************/ 

1 #include "mainwindow.h" 

2 #include <QCoreApplication> 

3 #include <QFileInfoList> 

4 #include <QDir> 

5 

6 MainWindow::MainWindow(QWidget *parent) 

7 : QMainWindow(parent) 

8 { 

9 /* 布局初始化 */ 

10 musicLayout(); 

11 

12 /* 媒体播放器初始化 */ 

13 mediaPlayerInit(); 

14 

15 /* 扫描歌曲 */ 

16 scanSongs(); 

17 

18 /* 按钮信号槽连接 */ 

19 connect(pushButton[0], SIGNAL(clicked()), 

20 this, SLOT(btn_previous_clicked())); 

21 connect(pushButton[1], SIGNAL(clicked()), 

22 this, SLOT(btn_play_clicked())); 

23 connect(pushButton[2], SIGNAL(clicked()), 

24 this, SLOT(btn_next_clicked())); 

25 

26 /* 媒体信号槽连接 */ 

27 connect(musicPlayer, 

28 SIGNAL(stateChanged(QMediaPlayer::State)), 

29 this, 

30 SLOT(mediaPlayerStateChanged(QMediaPlayer::State))); 

31 connect(mediaPlaylist, 

32 SIGNAL(currentIndexChanged(int)), 

33 this, 

34 SLOT(mediaPlaylistCurrentIndexChanged(int))); 

35 connect(musicPlayer, SIGNAL(durationChanged(qint64)), 

36 this, 

37 SLOT(musicPlayerDurationChanged(qint64))); 

38 connect(musicPlayer, 

39 SIGNAL(positionChanged(qint64)), 

40 this, 

41 SLOT(mediaPlayerPositionChanged(qint64))); 

42 

43 /* 列表信号槽连接 */ 

44 connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), 

45 this, SLOT(listWidgetCliked(QListWidgetItem*))); 

46 

47 /* slider 信号槽连接 */ 

48 connect(durationSlider, SIGNAL(sliderReleased()), 

49 this, SLOT(durationSliderReleased())); 

51 /* 失去焦点 */ 

52 this->setFocus(); 

53 } 

54 

55 void MainWindow::musicLayout() 

56 { 

57 /* 设置位置与大小,这里固定为 800, 480 */ 

58 this->setGeometry(0, 0, 800, 480); 

59 QPalette pal; 

60 

61 /* 按钮 */ 

62 for (int i = 0; i < 7; i++) 

63 pushButton[i] = new QPushButton(); 

64 

65 /* 标签 */ 

66 for (int i = 0; i < 4; i++) 

67 label[i] = new QLabel(); 

68 

69 for (int i = 0; i < 3; i++) { 

70 /* 垂直容器 */ 

71 vWidget[i] = new QWidget(); 

72 vWidget[i]->setAutoFillBackground(true); 

73 /* 垂直布局 */ 

74 vBoxLayout[i] = new QVBoxLayout(); 

75 } 

76 

77 for (int i = 0; i < 4; i++) { 

78 /* 水平容器 */ 

79 hWidget[i] = new QWidget(); 

80 hWidget[i]->setAutoFillBackground(true); 

81 /* 水平布局 */ 

82 hBoxLayout[i] = new QHBoxLayout(); 

83 } 

84 

85 /* 播放进度条 */ 

86 durationSlider = new QSlider(Qt::Horizontal); 

87 durationSlider->setMinimumSize(300, 15); 

88 durationSlider->setMaximumHeight(15); 

89 durationSlider->setObjectName("durationSlider"); 

90 

91 /* 音乐列表 */ 

92 listWidget = new QListWidget(); 

93 listWidget->setObjectName("listWidget"); 

94 listWidget->resize(310, 265); 

95 listWidget->setVerticalScrollBarPolicy( 

96 Qt::ScrollBarAlwaysOff); 

97 listWidget->setHorizontalScrollBarPolicy( 

98 Qt::ScrollBarAlwaysOff); 

99 

100 /* 列表遮罩 */ 

101 listMask = new QWidget(listWidget); 

102 listMask->setMinimumSize(310, 50); 

103 listMask->setMinimumHeight(50); 

104 listMask->setObjectName("listMask"); 

105 listMask->setGeometry(0, 

106 listWidget->height() - 50, 

107 310, 

108 50); 

109 

110 /* 设置对象名称 */ 

111 pushButton[0]->setObjectName("btn_previous"); 

112 pushButton[1]->setObjectName("btn_play"); 

113 pushButton[2]->setObjectName("btn_next"); 

114 pushButton[3]->setObjectName("btn_favorite"); 

115 pushButton[4]->setObjectName("btn_mode"); 

116 pushButton[5]->setObjectName("btn_menu"); 

117 pushButton[6]->setObjectName("btn_volume"); 

118 

119 /* 设置按钮属性 */ 

120 pushButton[1]->setCheckable(true); 

121 pushButton[3]->setCheckable(true); 

122 

123 /* H0 布局 */ 

124 vWidget[0]->setMinimumSize(310, 480); 

125 vWidget[0]->setMaximumWidth(310); 

126 vWidget[1]->setMinimumSize(320, 480); 

127 QSpacerItem *hSpacer0 = new 

128 QSpacerItem(70, 480, 

129 QSizePolicy::Minimum, 

130 QSizePolicy::Maximum); 

131 

132 QSpacerItem *hSpacer1 = new 

133 QSpacerItem(65, 480, 

134 QSizePolicy::Minimum, 

135 QSizePolicy::Maximum); 

136 

137 QSpacerItem *hSpacer2 = new 

138 QSpacerItem(60, 480, 

139 QSizePolicy::Minimum, 

140 QSizePolicy::Maximum); 

141 

142 hBoxLayout[0]->addSpacerItem(hSpacer0); 

143 hBoxLayout[0]->addWidget(vWidget[0]); 

144 hBoxLayout[0]->addSpacerItem(hSpacer1); 

145 hBoxLayout[0]->addWidget(vWidget[1]); 

146 hBoxLayout[0]->addSpacerItem(hSpacer2); 

147 hBoxLayout[0]->setContentsMargins(0, 0, 0, 0); 

148 

149 hWidget[0]->setLayout(hBoxLayout[0]); 

150 setCentralWidget(hWidget[0]); 

151 

152 /* V0 布局 */ 

153 listWidget->setMinimumSize(310, 265); 

154 hWidget[1]->setMinimumSize(310, 80); 

155 hWidget[1]->setMaximumHeight(80); 

156 label[0]->setMinimumSize(310, 95); 

157 label[0]->setMaximumHeight(95); 

158 QSpacerItem *vSpacer0 = new 

159 QSpacerItem(310, 10, 

160 QSizePolicy::Minimum, 

161 QSizePolicy::Maximum); 

162 QSpacerItem *vSpacer1 = new 

163 QSpacerItem(310, 30, 

164 QSizePolicy::Minimum, 

165 QSizePolicy::Minimum); 

166 vBoxLayout[0]->addWidget(label[0]); 

167 vBoxLayout[0]->addWidget(listWidget); 

168 vBoxLayout[0]->addSpacerItem(vSpacer0); 

169 vBoxLayout[0]->addWidget(hWidget[1]); 

170 vBoxLayout[0]->addSpacerItem(vSpacer1); 

171 vBoxLayout[0]->setContentsMargins(0, 0, 0, 0); 

172 

173 vWidget[0]->setLayout(vBoxLayout[0]); 

174 

175 /* H1 布局 */ 

176 for (int i = 0; i < 3; i++) { 

177 pushButton[i]->setMinimumSize(80, 80); 

178 } 

179 QSpacerItem *hSpacer3 = new 

180 QSpacerItem(40, 80, 

181 QSizePolicy::Expanding, 

182 QSizePolicy::Expanding); 

183 QSpacerItem *hSpacer4 = new 

184 QSpacerItem(40, 80, 

185 QSizePolicy::Expanding, 

186 QSizePolicy::Expanding); 

187 hBoxLayout[1]->addWidget(pushButton[0]); 

188 hBoxLayout[1]->addSpacerItem(hSpacer3); 

189 hBoxLayout[1]->addWidget(pushButton[1]); 

190 hBoxLayout[1]->addSpacerItem(hSpacer4); 

191 hBoxLayout[1]->addWidget(pushButton[2]); 

192 hBoxLayout[1]->setContentsMargins(0, 0, 0, 0); 

193 

194 hWidget[1]->setLayout(hBoxLayout[1]); 

195 

196 /* V1 布局 */ 

197 QSpacerItem *vSpacer2 = new 

198 QSpacerItem(320, 40, 

199 QSizePolicy::Minimum, 

200 QSizePolicy::Maximum); 

201 QSpacerItem *vSpacer3 = new 

202 QSpacerItem(320, 20, 

203 QSizePolicy::Minimum, 

204 QSizePolicy::Maximum); 

205 QSpacerItem *vSpacer4 = new 

206 QSpacerItem(320, 30, 

207 QSizePolicy::Minimum, 

208 QSizePolicy::Minimum); 

209 label[1]->setMinimumSize(320, 320); 

210 QImage Image; 

211 Image.load(":/images/cd.png"); 

212 QPixmap pixmap = QPixmap::fromImage(Image); 

213 int with = 320; 

214 int height = 320; 

215 QPixmap fitpixmap = 

216 pixmap.scaled(with, height, 

217 Qt::IgnoreAspectRatio, 

218 Qt::SmoothTransformation); 

219 label[1]->setPixmap(fitpixmap); 

220 label[1]->setAlignment(Qt::AlignCenter); 

221 vWidget[2]->setMinimumSize(300, 80); 

222 vWidget[2]->setMaximumHeight(80); 

223 vBoxLayout[1]->addSpacerItem(vSpacer2); 

224 vBoxLayout[1]->addWidget(label[1]); 

225 vBoxLayout[1]->addSpacerItem(vSpacer3); 

226 vBoxLayout[1]->addWidget(durationSlider); 

227 vBoxLayout[1]->addWidget(vWidget[2]); 

228 vBoxLayout[1]->addSpacerItem(vSpacer4); 

229 vBoxLayout[1]->setContentsMargins(0, 0, 0, 0); 

230 

231 vWidget[1]->setLayout(vBoxLayout[1]); 

232 

233 /* V2 布局 */ 

234 QSpacerItem *vSpacer5 = new 

235 QSpacerItem(300, 10, 

236 QSizePolicy::Minimum, 

237 QSizePolicy::Maximum); 

238 hWidget[2]->setMinimumSize(320, 20); 

239 hWidget[3]->setMinimumSize(320, 60); 

240 vBoxLayout[2]->addWidget(hWidget[2]); 

241 vBoxLayout[2]->addSpacerItem(vSpacer5); 

242 vBoxLayout[2]->addWidget(hWidget[3]); 

243 vBoxLayout[2]->setContentsMargins(0, 0, 0, 0); 

244 

245 vWidget[2]->setLayout(vBoxLayout[2]); 

246 

247 /* H2 布局 */ 

248 label[2]->setText("00:00"); 

249 label[3]->setText("00:00"); 

250 QFont font; 

251 

252 font.setPixelSize(10); 

253 

254 /* 设置标签文本 */ 

255 label[0]->setText("Q Music,Enjoy it!"); 

256 label[2]->setText("00:00"); 

257 label[3]->setText("00:00"); 

258 label[2]->setSizePolicy(QSizePolicy::Expanding, 

259 QSizePolicy::Expanding); 

260 label[3]->setSizePolicy(QSizePolicy::Expanding, 

261 QSizePolicy::Expanding); 

262 label[3]->setAlignment(Qt::AlignRight); 

263 label[2]->setAlignment(Qt::AlignLeft); 

264 label[2]->setFont(font); 

265 label[3]->setFont(font); 

266 

267 pal.setColor(QPalette::WindowText, Qt::white); 

268 label[0]->setPalette(pal); 

269 label[2]->setPalette(pal); 

270 label[3]->setPalette(pal); 

271 

272 hBoxLayout[2]->addWidget(label[2]); 

273 hBoxLayout[2]->addWidget(label[3]); 

274 

275 hBoxLayout[2]->setContentsMargins(0, 0, 0, 0); 

276 hWidget[2]->setLayout(hBoxLayout[2]); 

277 

278 /* H3 布局 */ 

279 QSpacerItem *hSpacer5 = new 

280 QSpacerItem(0, 60, 

281 QSizePolicy::Minimum, 

282 QSizePolicy::Maximum); 

283 QSpacerItem *hSpacer6 = new 

284 QSpacerItem(80, 60, 

285 QSizePolicy::Maximum, 

286 QSizePolicy::Maximum); 

287 QSpacerItem *hSpacer7 = new 

288 QSpacerItem(80, 60, 

289 QSizePolicy::Maximum, 

290 QSizePolicy::Maximum); 

291 QSpacerItem *hSpacer8 = new 

292 QSpacerItem(80, 60, 

293 QSizePolicy::Maximum, 

294 QSizePolicy::Maximum); 

295 QSpacerItem *hSpacer9 = new 

296 QSpacerItem(0, 60, 

297 QSizePolicy::Minimum, 

298 QSizePolicy::Maximum); 

299 

300 for (int i = 3; i < 7; i++) { 

301 pushButton[i]->setMinimumSize(25, 25); 

302 pushButton[i]->setMaximumSize(25, 25); 

303 } 

304 

305 hBoxLayout[3]->addSpacerItem(hSpacer5); 

306 hBoxLayout[3]->addWidget(pushButton[3]); 

307 hBoxLayout[3]->addSpacerItem(hSpacer6); 

308 hBoxLayout[3]->addWidget(pushButton[4]); 

309 hBoxLayout[3]->addSpacerItem(hSpacer7); 

310 hBoxLayout[3]->addWidget(pushButton[5]); 

311 hBoxLayout[3]->addSpacerItem(hSpacer8); 

312 hBoxLayout[3]->addWidget(pushButton[6]); 

313 hBoxLayout[3]->addSpacerItem(hSpacer9); 

314 hBoxLayout[3]->setContentsMargins(0, 0, 0, 0); 

315 hBoxLayout[3]->setAlignment(Qt::AlignHCenter); 

316 

317 hWidget[3]->setLayout(hBoxLayout[3]); 

318 

319 //hWidget[0]->setStyleSheet("background-color:red"); 

320 //hWidget[1]->setStyleSheet("background-color:#ff5599"); 

321 //hWidget[2]->setStyleSheet("background-color:#ff55ff"); 

322 //hWidget[3]->setStyleSheet("background-color:black"); 

323 //vWidget[0]->setStyleSheet("background-color:#555555"); 

324 //vWidget[1]->setStyleSheet("background-color:green"); 

325 //vWidget[2]->setStyleSheet("background-color:gray"); 

326 

327 } 

328 

329 MainWindow::~MainWindow() 

330 { 

331 } 

332 

333 void MainWindow::btn_play_clicked() 

334 { 

335 int state = musicPlayer->state(); 

336 

337 switch (state) { 

338 case QMediaPlayer::StoppedState: 

339 /* 媒体播放 */ 

340 musicPlayer->play(); 

341 break; 

342 

343 case QMediaPlayer::PlayingState: 

344 /* 媒体暂停 */ 

345 musicPlayer->pause(); 

346 break; 

347 

348 case QMediaPlayer::PausedState: 

349 musicPlayer->play(); 

350 break; 

351 } 

352 } 

353 

354 void MainWindow::btn_next_clicked() 

355 { 

356 musicPlayer->stop(); 

357 int count = mediaPlaylist->mediaCount(); 

358 if (0 == count) 

359 return; 

360 

361 /* 列表下一个 */ 

362 mediaPlaylist->next(); 

363 musicPlayer->play(); 

364 } 

365 

366 void MainWindow::btn_previous_clicked() 

367 { 

368 musicPlayer->stop(); 

369 int count = mediaPlaylist->mediaCount(); 

370 if (0 == count) 

371 return; 

372 

373 /* 列表上一个 */ 

374 mediaPlaylist->previous(); 

375 musicPlayer->play(); 

376 } 

377 

378 void MainWindow::mediaPlayerStateChanged( 

379 QMediaPlayer::State 

380 state) 

381 { 

382 switch (state) { 

383 case QMediaPlayer::StoppedState: 

384 pushButton[1]->setChecked(false); 

385 break; 

386 

387 case QMediaPlayer::PlayingState: 

388 pushButton[1]->setChecked(true); 

389 break; 

390 

391 case QMediaPlayer::PausedState: 

392 pushButton[1]->setChecked(false); 

393 break; 

394 } 

395 } 

396 

397 void MainWindow::listWidgetCliked(QListWidgetItem *item) 

398 { 

399 musicPlayer->stop(); 

400 mediaPlaylist->setCurrentIndex(listWidget->row(item)); 

401 musicPlayer->play(); 

402 } 

403 

404 void MainWindow::mediaPlaylistCurrentIndexChanged( 

405 int index) 

406 { 

407 if (-1 == index) 

408 return; 

409 

410 /* 设置列表正在播放的项 */ 

411 listWidget->setCurrentRow(index); 

412 } 

413 

414 void MainWindow::musicPlayerDurationChanged( 

415 qint64 duration) 

416 { 

417 durationSlider->setRange(0, duration / 1000); 

418 int second = duration / 1000; 

419 int minute = second / 60; 

420 second %= 60; 

421 

422 QString mediaDuration; 

423 mediaDuration.clear(); 

424 

425 if (minute >= 10) 

426 mediaDuration = QString::number(minute, 10); 

427 else 

428 mediaDuration = "0" + QString::number(minute, 10); 

429 

430 if (second >= 10) 

431 mediaDuration = mediaDuration 

432 + ":" + QString::number(second, 10); 

433 else 

434 mediaDuration = mediaDuration 

435 + ":0" + QString::number(second, 10); 

436 

437 /* 显示媒体总长度时间 */ 

438 label[3]->setText(mediaDuration); 

439 } 

440 

441 void MainWindow::mediaPlayerPositionChanged( 

442 qint64 position) 

443 { 

444 if (!durationSlider->isSliderDown()) 

445 durationSlider->setValue(position/1000); 

446 

447 int second = position / 1000; 

448 int minute = second / 60; 

449 second %= 60; 

450 

451 QString mediaPosition; 

452 mediaPosition.clear(); 

453 

454 if (minute >= 10) 

455 mediaPosition = QString::number(minute, 10); 

456 else 

457 mediaPosition = "0" + QString::number(minute, 10); 

458 

459 if (second >= 10) 

460 mediaPosition = mediaPosition 

461 + ":" + QString::number(second, 10); 

462 else 

463 mediaPosition = mediaPosition 

464 + ":0" + QString::number(second, 10); 

465 

466 /* 显示现在播放的时间 */ 

467 label[2]->setText(mediaPosition); 

468 } 

469 

470 void MainWindow::resizeEvent(QResizeEvent *event) 

471 { 

472 Q_UNUSED(event); 

473 listMask->setGeometry(0, 

474 listWidget->height() - 50, 

475 310, 

476 50); 

477 } 

478 

479 void MainWindow::durationSliderReleased() 

480 { 

481 /* 设置媒体播放的位置 */ 

482 musicPlayer->setPosition(durationSlider->value() * 1000); 

483 } 

484 

485 void MainWindow::scanSongs() 

486 { 

487 QDir dir(QCoreApplication::applicationDirPath() 

488 + "/myMusic"); 

489 QDir dirbsolutePath(dir.absolutePath()); 

490 /* 如果目录存在 */ 

491 if (dirbsolutePath.exists()) { 

492 /* 定义过滤器 */ 

493 QStringList filter; 

494 /* 包含所有.mp3 后缀的文件 */ 

495 filter << "*.mp3"; 

496 /* 获取该目录下的所有文件 */ 

497 QFileInfoList files = 

498 dirbsolutePath.entryInfoList(filter, QDir::Files); 

499 /* 遍历 */ 

500 for (int i = 0; i < files.count(); i++) { 

501 MediaObjectInfo info; 

502 /* 使用 utf-8 编码 */ 

503 QString fileName = QString::fromUtf8(files.at(i) 

504 .fileName() 

505 .replace(".mp3", "") 

506 .toUtf8() 

507 .data()); 

508 info.fileName = fileName + "\n" 

509 + fileName.split("-").at(1); 

510 info.filePath = QString::fromUtf8(files.at(i) 

511 .filePath() 

512 .toUtf8() 

513 .data()); 

514 /* 媒体列表添加歌曲 */ 

515 if (mediaPlaylist->addMedia( 

516 QUrl::fromLocalFile(info.filePath))) { 

517 /* 添加到容器数组里储存 */ 

518 mediaObjectInfo.append(info); 

519 /* 添加歌曲名字至列表 */ 

520 listWidget->addItem(info.fileName); 

521 } else { 

522 qDebug()<< 

523 mediaPlaylist->errorString() 

524 .toUtf8().data() 

525 << endl; 

526 qDebug()<< " Error number:" 

527 << mediaPlaylist->error() 

528 << endl; 

529 } 

530 } 

531 } 

532 } 

533 

534 void MainWindow::mediaPlayerInit() 

535 { 

536 musicPlayer = new QMediaPlayer(this); 

537 mediaPlaylist = new QMediaPlaylist(this); 

538 /* 确保列表是空的 */ 

539 mediaPlaylist->clear(); 

540 /* 设置音乐播放器的列表为 mediaPlaylist */ 

541 musicPlayer->setPlaylist(mediaPlaylist); 

542 /* 设置播放模式,Loop 是列循环 */ 

543 mediaPlaylist->setPlaybackMode(QMediaPlaylist::Loop); 

544 } 

第 10 行,布局初始化,第一步我们先建立好界面,确定好布局再实现功能,一般流程都这
样,布局 msuicLayout()的内容比较多,也不难,但是比较复杂,如果我们有第七章的基础,看
这种布局是没有难度的,这里就不多解释了。没有好看的布局也能完成本例。如果您喜欢这种
布局方法,您需要多花点时间去研究如何布局才好看,这些没有固定的方法,完全是一个人的
审美感。
第 13 行,媒体先初始化,初始化媒体播放器与媒体播放列表。
第 16 行,扫描歌曲,初始化本地歌曲,从固定的文件夹里找歌曲文件,这里笔者设计从固
定的文件夹里找歌曲文件。也有些读者可能会说可以自由选择文件夹吗?答案是可以的!使用

QFileDilog 类打开选择歌曲目录或者文件即可!但是在嵌入式里,一般是初始化界里面就已经
有歌曲在界面里的了,无需用户再去打开,打开歌曲这种操作是极少会使用的!
第 26 至 47 行,信号槽连接,这里使用了各种各样的信号。这里有必要说明一下,笔者设
计了单击歌曲列表就能播放歌曲了。如果在电脑上可能有些播放器软件会双击才能播放歌曲,
在嵌入式的触摸屏里,只有单击!没有双击,没有用户会双击歌曲的列表的。这些特殊的地方
我们需要在嵌入式里考虑!
第 333~376 行,点击播放按钮,上一曲,下一曲,Qt 的媒体类已经提供了 previous(),next(),

stop(),play(),pause()这些方法直接可以使用。除了实现好看的界面之外,这部分内容也是本
例实现播放器重要的部分!
其他部分是实现播放状态的切换及扩进度条的显示进度处理,请参阅源码理解。
main.cpp 内容如下,主要是加载 qss 样式文件。没有什么可讲解。

1 #include "mainwindow.h" 

2 

3 #include <QApplication> 

4 #include <QFile> 

5 

6 int main(int argc, char *argv[]) 

7 { 

8 QApplication a(argc, argv); 

9 /* 指定文件 */ 

10 QFile file(":/style.qss"); 

11 

12 /* 判断文件是否存在 */ 

13 if (file.exists() ) { 

14 /* 以只读的方式打开 */ 

15 file.open(QFile::ReadOnly); 

16 /* 以字符串的方式保存读出的结果 */ 

17 QString styleSheet = QLatin1String(file.readAll()); 

18 /* 设置全局样式 */ 

19 qApp->setStyleSheet(styleSheet); 

20 /* 关闭文件 */ 

21 file.close(); 

22 } 

23 

24 MainWindow w; 

25 w.show(); 

26 return a.exec(); 

27 } 

style.qss 样式文件如下。素材已经在源码处提供。注意下面的 style.qss 不能有注释!

1 QWidget { 

2 background: "#25242a" 

3 } 

4 

5 QWidget#listMask { 

6 border-image: url(:/images/mask.png); 

7 background-color: transparent; 

8 } 

9 

10 QListWidget#listWidget { 

11 color:white; 

12 font-size: 15px; 

13 border:none; 

14 } 

15 

16 QListWidget#listWidget:item:active { 

17 background: transparent; 

18 } 

19 

20 QListWidget#listWidget:item { 

21 background: transparent; 

22 height:60; 

23 } 

24 

25 QListWidget#listWidget:item:selected { 

26 color:#5edcf3; 

27 background: transparent; 

28 } 

29 

30 QListWidget#listWidget:item:hover { 

31 background: transparent; 

32 color:#5edcf3; 

33 border:none; 

34 } 

35 

36 QPushButton#btn_play { 

37 border-image:url(:/images/btn_play1.png); 

38 } 

39 

40 QPushButton#btn_play:hover { 

41 border-image:url(:/images/btn_play2.png); 

42 } 

43 

44 QPushButton#btn_play:checked { 

45 border-image:url(:/images/btn_pause1.png); 

46 } 

47 

48 QPushButton#btn_play:checked:hover { 

49 border-image:url(:/images/btn_pause2.png); 

50 } 

51 

52 QPushButton#btn_previous { 

53 border-image:url(:/images/btn_previous1.png); 

54 } 

55 

56 QPushButton#btn_previous:hover { 

57 border-image:url(:/images/btn_previous2.png); 

58 } 

59 

60 QPushButton#btn_next { 

61 border-image:url(:/images/btn_next1.png); 

62 } 

63 

64 QPushButton#btn_next:hover { 

65 border-image:url(:/images/btn_next2.png); 

66 } 

67 

68 QPushButton#btn_favorite { 

69 border-image:url(:/images/btn_favorite_no.png); 

70 } 

71 

72 QPushButton#btn_favorite:checked { 

73 border-image:url(:/images/btn_favorite_yes.png); 

74 } 

75 

76 QPushButton#btn_menu { 

77 border-image:url(:/images/btn_menu1.png); 

78 } 

79 

80 QPushButton#btn_menu:hover { 

81 border-image:url(:/images/btn_menu2.png); 

82 } 

83 

84 QPushButton#btn_mode { 

85 border-image:url(:/images/btn_listcircle1.png); 

86 } 

87 

88 QPushButton#btn_mode:hover { 

89 border-image:url(:/images/btn_listcircle2.png); 

90 } 

91 

92 QPushButton#btn_mode { 

93 border-image:url(:/images/btn_listcircle1.png); 

94 } 

95 

96 QPushButton#btn_mode:hover { 

97 border-image:url(:/images/btn_listcircle2.png); 

98 } 

99 

100 QPushButton#btn_volume { 

101 border-image:url(:/images/btn_volume1.png); 

102 } 

103 

104 QPushButton#btn_volume:hover { 

105 border-image:url(:/images/btn_volume2.png); 

106 } 

107 

108 QSlider#durationSlider:handle:horizontal { 

109 border-image:url(:/images/handle.png); 

110 } 

111 

112 QSlider#durationSlider:sub-page:horizontal { 

113 border-image:url(:/images/sub-page.png); 

114 } 

程序运行效果

先点击构建项目,项目构建完成后,再将本例的 myMusic 歌曲文件夹拷贝到可执行程序的
文件夹同一级目录下,也就是 build-14_musicplayer-Desktop_Qt_5_12_9_GCC_64bit-Debug 目录
下(windows 需要进入到 debug 目录)。再点击运行,就出现歌曲在列表里,如下图,点击播放
即可播放歌曲,上一曲,下一曲也可以用。注意右下角的某些按钮功能,在本例没有继续去实
现,比如音量控制,可以直接加一个垂直方向的滑条,然后控制媒体的软件音量即可。留给读
者自由发挥,可以基于本例去开发,就当读者练习吧。本例的界面开发笔者还是比较满意的,
前面的界面都比较普通,笔者个人 Qt 开发重要的是界面与稳定性,功能是次要的!因为功能都
不难实现。

注意歌曲格式应严格为歌名 + “-” + 歌手名称.mp3,例如江南 - 林俊杰.mp3。中间的
“-”是英文字符的短横杠,这样的目的是能够将歌曲名称和歌手分开显示到界面上。
在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
很抱歉,我没有找到关于"Qtcreate"的相关信息。请问您是指"Qt Creator"吗?Qt Creator是一个集成开发环境(IDE),用于开发Qt应用程序。它支持多种平台,包括iOS、Android和WinRT。通过Qt Creator,您可以编写和调试代码,并使用Qt的字符串类,如QString和QByteArray,来处理字符串。QString是Qt最常用的字符串类,而QByteArray适用于处理以'\0'结尾的传统字符串。QByteArray可以处理多字节编码的字符串,如UTF-8、GBK和Big5。在使用QByteArray时,程序员需要确定所使用的字符串编码格式。此外,QByteArray还使用了隐式共享机制来提高运行效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Qt Create 笔记 (一) 1.QString 2.QByteArray](https://blog.csdn.net/linbounconstraint/article/details/51497782)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Game Programming Using QT(PACKT,2016)](https://download.csdn.net/download/vanridin/9431499)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ManGo CHEN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值