3.1.1 在 widget.h 定义 QListWidge 对象指针
3.1.2 在 memberInit 函数中添加 QlistWidge 初始化
3.1.3 在 setMusicPlayStyle 函数中设置其风格
扫描二维码关注公众号,回复:
16649318 查看本文章
8.6 在 updatePlayPauseBtnStateSlot 函数中添加定时器开关
1、实现功能
音乐播放所实现的功能有:
1
) 播放
/
暂停功能,
2
) 上一首
/
下一首,
3
) 设置音量,
4
) 设置播放模式,
5
) 双击歌曲列表的歌曲名可以播放音乐,
6
) 播放音乐的时候可以显示要播放的歌曲名。
7
) 显示当前播放的时间以及当前音乐的总时间。
8
) 滑动改变音乐的播放进度
2、音乐播放界面
其界面的布局是采用
ui
界面进行布局,没有使用程序代码进行布局的,在程序中,当然也可以使用 程序代码界面进行布局,此处部分是 ui
程序代码布局,播放列表使用程序布局。
2.1 界面程序
2.1.1 界面控制初始化
//控件初始化
void Widget::memberInit()
{
QIcon scanIcon(QPixmap(":/music/resource/player/player_icon/open.png"));
QIcon palyIcon(QPixmap(":/music/resource/player/player_icon/list.png"));
ui->scanLocalFileBtn->setIconSize(QSize(40,40));
ui->scanLocalFileBtn->setIcon(scanIcon);
ui->showPlayListBtn->setIconSize(QSize(40,40));
ui->showPlayListBtn->setIcon(palyIcon);
QIcon sequenceIcon(QPixmap(":/music/resource/player/player_icon/列表循
环.png"));
QIcon onceIcon(QPixmap(":/music/resource/player/player_icon/单曲循环.png"));
QIcon rangeIcon(QPixmap(":/music/resource/player/player_icon/随机播放.png"));
QIcon onceSignle(QPixmap(":/music/resource/player/player_icon/单曲一次.png"));
QIcon stepPlay(QPixmap(":/music/resource/player/player_icon/顺序播放.png"));
ui->playModelCbox->addItem(stepPlay,"顺序播放");
ui->playModelCbox->addItem(onceSignle,"单曲一次");
ui->playModelCbox->addItem(onceIcon,"单曲循环");
ui->playModelCbox->addItem(sequenceIcon,"循环播放");
ui->playModelCbox->addItem(rangeIcon,"随机播放");
//音量滑条的范围 40~100 声音的范围(测试 40 以上有声音)
ui->volumeSlider->setRange(0,100);
//设置音量滑条的初始值为 70
ui->volumeSlider->setValue(50);
}
2.1.2 控件风格程序
void Widget::setMusicPlayStyle()
{
//设置播放器背景图片 通过调色板实现
QString musicBack = ":/music/resource/player/播放器背景.png";
playerPalette.setBrush(QPalette::Background,QBrush(QPixmap(musicBack)));
this->setPalette(playerPalette);
this->setAutoFillBackground(true);
//上一首
ui->preSongBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/prev.png);"
"border-radius:10px;"
);
//下一首
ui->nextSongBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/next.png);"
"border-radius:10px;"
);
//播放
ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/play.png);"
"border-radius:10px;"
);
//播放模式
ui->playModelCbox->setStyleSheet("background: url(:/music/resource/player/播放
器背景.png);"
"border: 1px solid gray;"
"border-radius:5px;"
"min-width: 6em;"
"font: 15px;"
"color: #FFFFFF;"
);
//改变播放滑条和音量滑条的样式表
ui->playProgressSlider->setStyleSheet("QSlider::groove:horizontal{border:0px;height
:4px;}"
"QSlider::subpage:horizontal{background:red;}"
"QSlider::addpage:horizontal{background:lightgray;}"
"QSlider::handle:horizontal{background:white;width:10px;border-radius:5px;margin:-
3px 0px -3px 0px;}");
ui->volumeSlider->setStyleSheet( "QSlider::groove:horizontal{border:0px;height:4px;
}"
"QSlider::subpage:horizontal{background:red;}"
"QSlider::addpage:horizontal{background:lightgray;}"
"QSlider::handle:horizontal{background:white;width:10px;border-radius:5px;margin:-
3px 0px -3px 0px;}");
//扫描歌曲 播放列表 返回 关闭 透明
ui->scanLocalFileBtn->setStyleSheet("background: transparent;"
"border: 1px solid gray;"
"border-radius:6px;"
"color: #FFFFFF;"
"font:16px;"
"min-width: 4em;"
);
ui->showPlayListBtn->setStyleSheet("background: transparent;"
"border: 1px solid gray;"
"border-radius:6px;"
"color: #FFFFFF;"
"font:16px;"
"min-width: 4em;"
);
ui->closeBtn->setStyleSheet("background: transparent;"
"border: 1px solid gray;"
"border-radius:6px;"
"color: #FFFFFF;"
"font:16px;"
"min-width: 4em;"
);
ui->blackBtn->setStyleSheet("background: transparent;"
"border: 1px solid gray;"
"border-radius:6px;"
"color: #FFFFFF;"
"font:16px;"
"min-width: 4em;"
);
//歌曲名
ui->songNameLb->setStyleSheet("font:18px;""color:#FFFFFF;");
3、 歌曲列表界面
使用程序创建 QListWidget 控件来显示歌曲列表。
3.1.1 在 widget.h 定义 QListWidge 对象指针
QListWidget *showPlayList;
3.1.2 在 memberInit 函数中添加 QlistWidge 初始化
//显示列表初始化
showPlayList = new QListWidget; //列表显示 --通过程序创建控制
showPlayList->setMinimumSize(400,500);
showPlayList->setMaximumSize(400,500);
showPlayList->setWindowTitle("播放列表");
showPlayList->setWindowIcon(QIcon(QPixmap(":/music/resource/image/music.png")));
//设置显示列表显示的位置跟音乐部件的显示位置同一个高度,在音乐部件的后面,x 坐
标为音乐部件的宽度
this->move(500,300);
showPlayList->move(this->width()+510,this->y());
playListBtnState = true; //false 隐藏,true 显示
showPlayList->show();
3.1.3 在 setMusicPlayStyle 函数中设置其风格
//设置显示列表的背景
showPlayList->setStyleSheet("QListWidget{color:#D4D4D4;"
"font:17px;"
"backgroundimage:url(:/music/resource/player/playerlist/播放器列表背景.png);}");
4、音乐播放功能的实现
因为是基于
Linux
平台下实现
Qt
的音乐播放,如果利用
Qt
现有的提供的多媒体播放器
QMediaPlayer 进行实现的话, 只能是用于 Windows
平台下的实现,是不支持
Linux
平台下, 因为
Qt5
多媒体播放使用QMediaPlayer,而
QMediaPlayer
使用
gstreamer
后端来播放媒体, gstreamer 又不能移植到
arm
。 所以最后决 定在 Qt5
上,使用
QProcess
直接调
MPlayer
的方式来实现音乐播放功能。 在这里将列举出该程序中使用到的核心功能。
4.1 获取本地歌曲
/****************************************************
* 函数原型:void getLocalFileSots()
* 函数功能:获取本地音乐文件槽函数
*****************************************************/
void Widget::getLocalFileSots()
{
//获取选择的文件目录名
QString fileNameDir = QFileDialog::getExistingDirectory(this,"选择音乐文件
","../music");
if(fileNameDir.isEmpty())
{
return;
}
//对目录进行扫描操作,需要目录类,利用目录路径构造目录类对象
//1.利用 带路径的目录名 构造目录类对象
QDir dir(fileNameDir);
//2.编写 过滤的文件格式
QStringList formatList;
formatList << "*.mp3" << "*.mp4" << "*.wma";
//3. 创建文件信息列表
//QFileInfoList infoList;
//4. 按照过滤的文件格式扫描文件,选择符合格式的文件
infoList = dir.entryInfoList(formatList);
if(infoList.isEmpty())
{
return;
}
//显示列表显示歌名的时候,前面加显示图标,显示图标的位置
QIcon musicMap(QPixmap(":/music/resource/player/playerlist/音符 1.png"));
for(int i = 0; i < infoList.count(); i++)
{
//需要检测是否重复
//媒体播放内容列表需要带路径的文件名
playListString << infoList[i].filePath();
//显示给用户的列表只需要显示文件名,并在显示列表前面加图标
QListWidgetItem *songNameList = new
QListWidgetItem(musicMap,infoList[i].fileName());
songNameList->setSizeHint(QSize(400,40));
showPlayList->addItem(songNameList);
//打印文件路径 和文件名
//qDebug() << infoList[i].fileName(); //不带路径的文件名
//qDebug() << infoList[i].filePath(); //带路径的文件名
}
showPlayList->setCurrentRow(0);
}
4.1.1 显示歌曲列表
/****************************************************dddddd
* 函数原型:void updatePlayFileListBtnStateSlots()
* 函数功能:更新显示文件列表的状态
* 该显示文件列表要么显示,要么被隐藏
* 说明:
* playListBtnState == true 显示列表
* playListBtnState == false 隐藏列表
*****************************************************/
void Widget::updatePlayFileListBtnStateSlots()
{
//跟以前状态相反
playListBtnState = !playListBtnState;
QIcon showIcon(QPixmap(":/music/resource/player/player_icon/列表.png"));
QIcon hideIcon(QPixmap(":/music/resource/player/player_icon/隐藏列表.png"));
switch (playListBtnState)
{
case true:
showPlayList->show(); //显示
ui->showPlayListBtn->setIcon(hideIcon);
break;
case false:
showPlayList->hide(); //隐藏
ui->showPlayListBtn->setIcon(showIcon);
break;
}
}
5、Qprocess 实现 MPlayer
5.1 QT使用进程
程序:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
myProcess = new QProcess(this);
connect(myProcess,SIGNAL(readyRead()),this,SLOT(doSlotProcessReadyRead()));
}
void Widget::on_btnExec_clicked()
{
QString cmd = ui->lEditCmd->text();
QString arg = ui->lEditArg->text();
QStringList arrayArg = arg.split(" "); //获取所有的参数
myProcess->start(cmd,arrayArg);
}
void Widget::doSlotProcessReadyRead(){
while(!myProcess->atEnd()){
//readLine 返回的是 QByteArray,转为 QString ,replace("\n","")去掉\n
QString str = QString(myProcess->readLine()).replace("\n","");
ui->textEdit->append(str);
}
}
5.2 QProcess 调用 MPlayer 方法
我们只需要
new
一个
QProcess,
然后通过
QProcess
的
start
方法启动
mplayer
线程即可.如下:
process = new QProcess();QStringList args;args << "-slave"; // 使用 slave 模式args << "-quiet"; // 不要输出冗余信息_process->start("mplayer", args); // 启动该进程,并传入参数 args
注意:这里的 mplayer 需要添加绝对路径, 也就是你当前 mplayer 所存放的位置
然后接下来这样,便可以启动
mplayer
。如果我们要控制
mplaer
呢,使用
QProcess
的
write
方法,往 mplayer 写入命令即可,比如如下:
process->write("pause\n");
如果要读取 mplayer 发出来的消息呢,使用 QProcess 的 readLine 方法,方式如下:
_process->readLine(data,200);
这样便可以读取一行 mplayer 发送出来的信息,然后我们只需要解析这个 data 即可。
6、Mplayer命令大全
loadfile name // 加载媒体文件 namevolume 100 1 // 设置音量,中间位音量的大小 0-100seek 50 1 // 设置进度, 50 代表进度大小 ( 百分比 ) , 0-100 //0 is a relative seek of +/- <value> seconds (default).//1 is a seek to <value> % in the movie.//2 is a seek to an absolute position of <value> seconds.mute 1/0 // 静音开关pause // 播放 / 暂停get_time_length // 获取播放文件的总时间,以秒为单位seek value // 定位, valu 为秒数get_percent_pos // 获取播放的百分比get_time_pos // 获取当前播放的位置,以秒为单位get_file_name // 获取当前播放的媒体文件名get_meta_album // 获取专辑get_meta_artist // 获取艺术家get_meta_comment // 获取评论get_meta_genre // 获取流派get_meta_title // 获取标题get_meta_year // 获取年份
7、实现播放和暂停功能
7.1 播放器初始化
在头文件
musicplay
中,添加相关成员的声明之后,然后在源文件中实现,首先是对播放器的初始化如下:
//初始化播放器
void Widget::MaplayerInit()
{
//创建播放进程
playProcess = new QProcess(this);
playProcess->setProcessChannelMode(QProcess::MergedChannels);
program = "/usr/bin/mplayer"; //X86 架构下
//program = "/usr/local/bin/mplayer"; //mplayer 命令路径,一定要正确,不然无法
播放 –ARM 架构
playState = false; //播放状态
playBtnState = false; //播放按钮状态
playIndex = 0; //播放内容下标,跟显示列表的内容要保持一致
}
7.2 播放函数实现
void Widget::playMusic()
{
//如果没有加载播放内容
playProcess->close();
args.clear();
args << "-slave"; //使用 slave 模式
args << "-quiet"; //不要输出冗余信息
args << playListString[playIndex];
qDebug() << " playListString[playIndex]: " << playListString[playIndex];
QString str = "正在播放: " + showPlayList->currentItem()->text();
ui->songNameLb->setText(str); //显示正在播放的音乐
playProcess->start(program,args); //开始播放
playProcess->write("volume 70 1\n");
playState = true;
}
7.3 播放按钮功能实现
/****************************************************
* 函数原型:void updatePlayPauseBtnStateSlot()
* 函数功能:更新播放暂停按钮状态
*****************************************************/
void Widget::updatePlayPauseBtnStateSlot()
{
playBtnState = !playBtnState;
switch(playBtnState)
{
case true:
if(!playState) {
playMusic();
}
else
{
playProcess->write("pause\n");
}
ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/暂停.png);"
"border-radius:10px;"
);
break;
case false:
playProcess->write("pause\n");
ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/播放.png);"
"border-radius:10px;"
);
break;
}
}
8、获取总时间和当前时间
8.1 在 MaplayerInit 函数中添加相关槽函数
//初始化播放器
void Widget::MaplayerInit()
{
//关联相关的信号,进程启动成功,出错,有数据可读等
connect(playProcess,SIGNAL(started()),this,SLOT(onStartedSlot()));
connect(playProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onErrorSlot()))
;
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSlot()));
connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinishedSlot()));
//创建定时器--定时器的主要功能, 就是用于定时获取当前音乐的播放时间, 然后进行
转换为当前的播放时间
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(onTimeoutSlot()));
}
8.2 在开始播放槽函数发送获取总时间命令
void Widget::onStartedSlot()
{
qDebug() << "准备播放";
//获取播放文件的长度以毫秒为单位
playProcess->write("get_time_length\n");
}
8.3 在获取数据槽函数中获取总时间和当前时间
void Widget::onReadDataSlot()
{
while (playProcess->bytesAvailable()) {
QByteArray arr = playProcess->readLine();
QString str = QString::fromLocal8Bit(arr);
if(str.contains("ANS_LENGTH"))
{
//获取时间总长度
qDebug() << "::"<<str;
str.remove("\n");
str.remove("\r");
str.remove("ANS_LENGTH=");
qDebug() << "str = " << str ;
int t = str.toDouble();
int m = t / 60;
int s = t % 60;
tlength = m * 60 + s;
qDebug() << "tlength " << tlength;
//设置播放进度的总数值
ui->playProgressSlider->setMinimum(0);
ui->playProgressSlider->setMaximum(tlength);
ui->playProgressSlider->setSingleStep(1);
QString timeLength;
timeLength.sprintf("%02d:%02d",m,s);
ui->totleTimeLb->setText(timeLength);
}
if(str.contains("ANS_TIME_POSITION") )
{
//获取当前时间
//qDebug() << "当前时间:: " << str ;
str.remove("\n");
str.remove("\r");
double t = QString(str.split("=").at(1)).toDouble();
//显示当前时间
int m = t / 60;
int s = (int)(t+0.5) % 60; //四舍五入防止少时间
QString timePos;
timePos.sprintf("%02d:%02d",m,s);
ui->currentTimeLb->setText(timePos);
int now = (m * 60 + s);
//double slider = now *100 /tlength;
//设置播放进度当前滑条的值
ui->playProgressSlider->setValue(now);
}
}
}
8.4 在定时器槽函数中发送获取当前时间命令
void Widget::onTimeoutSlot()
{
//获取当前播放的位置,以秒为单位
playProcess->write("get_time_pos\n");
}
8.5 在 playMusic 函数中启动定时器
void Widget::playMusic()
{
…..
// 定时器开启
timer->start(100);
}
8.6 在 updatePlayPauseBtnStateSlot 函数中添加定时器开关
void Widget::updatePlayPauseBtnStateSlot()
{
playBtnState = !playBtnState;
switch(playBtnState)
{
case true:
if(!playState) {
playMusic(); //第一次播放
}
else
{
playProcess->write("pause\n");
timer->start(); →暂停后再次播放时启动定时器
}
…
break;
case false:
playProcess->write("pause\n");
timer->stop();→暂停播放时关闭定时器
….
break;
}}
9、双击播放功能
9.1 关联信号与槽
//显示列表用户双击信号关联指定音乐文件的槽函数
connect(showPlayList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedToPl
ayerMusicSlots()));
9.2 编写槽函数
/****************************************************
* 函数原型:void loadMusicToPlayerSlots()
* 函数功能:加载指定音乐到播放列表槽函数
* 用户通过双击选择需要播放的音乐
*****************************************************/
void Widget::doubleClickedToPlayerMusicSlots()
{
//获取显示列表的当前行
int row = showPlayList->currentRow();
playIndex = row;
playState = false; //双击之后需要播放音乐
playBtnState = false; //无论之前是什么状态,双击之后必须播放
updatePlayPauseBtnStateSlot(); //更新播放暂停按钮—实现播放
}
10、音量设置
10.1 关联信号与槽
//音量改变信号
connect(ui->volumeSlider,SIGNAL(sliderMoved(int)),this,SLOT(setVolumeSlot(int)));
10.2 实现槽函数
void Widget::setVolumeSlot(int volume)
{
QString str = QString("volume ");
if(playProcess->isOpen())
{
QString buf;
buf.setNum(volume);
str += buf + " 1\n";
//playProcess->write("volume %d 1\n",volume);
playProcess->write(str.toLocal8Bit());
}
}
11、歌曲切换
11.1 播放模式设置
11.1.1 使用枚举定义播放模式(类内定义枚举)
public:
typedef enum
{
ListPlay = 0, //顺序播放
SingleSongOnce = 1, //单曲一次
SingleSongLoop = 2, //单曲循环
PlayListLoop = 3, //列表循环
RandomPlay = 4, //随机播放
}PlayModel;
11.1.2 关联信号与槽
//模式选择关联 更新播放按钮槽函数
connect(ui->playModelCbox,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePlayMode
Slots(int)));
11.1.3 实现槽函数
/****************************************************
* 函数原型:void updatePlayModeSlots(int index)
* 函数功能:更新播放模式,获取用户选择的模式
* 用户选择的模式跟系统的模式顺序关联
*****************************************************/
void Widget::updatePlayModeSlots(int index)
{
switch (index)
{
case 0:
//顺序播放
playModel = ListPlay;
break;
case 1:
//单曲一次
playModel = SingleSongOnce;
break;
case 2:
//单曲循环
playModel = SingleSongLoop;
break;
case 3:
//循环播放
playModel = PlayListLoop;
break;
case 4:
//随机播放
playModel = RandomPlay;
break;
}
}
11.2 上一曲
11.2.1 关联信号与槽
//上一首
connect(ui->preSongBtn,SIGNAL(clicked(bool)),this,SLOT(playPrevSongSlot()));
11.2.2 实现槽函数
void Widget::playPrevSongSlot()
{
if(playIndex > 0)
{
if(playModel == RandomPlay) //随机播放
{
qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
playIndex = qrand() %(playListString.count()-1); //产生
playListString.count()-1 以内的随机数
}
else
{
playIndex--;
}
playState = false; //点击上一首之后需要播放音乐
playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放
updatePlayPauseBtnStateSlot();
//发送播放内容改变信号
emit playConcentChanged(playIndex);
}else{//回到最后一首
if(playModel == RandomPlay) //随机播放
{
qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
playIndex = qrand() %(playListString.count()-1); //产生
playListString.count()-1 以内的随机数
}
else
{
playIndex=playListString.count()-1;
}
playState = false; //点击上一首之后需要播放音乐
playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放
updatePlayPauseBtnStateSlot();
//发送播放内容改变信号
emit playConcentChanged(playIndex);
}
11.2.3 槽函数发送自定义播放内容
signals:
void playConcentChanged(int index); //播放内容改变信号,播放内容改变,发送改变的
下标
11.2.4 关联自定义信号与槽
//媒体内容列表行改变(下一首、上一首、一首歌播放结束) 关联 显示列表行改变槽函数
connect(this,SIGNAL(playConcentChanged(int)),this,SLOT(updateShowPlayListRow(int)))
;
//双击当前行 播放内容改变(下一首、上一首、一首歌播放结束) 歌曲名更新
connect(showPlayList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(updateSongTitleSl
ot()));
11.2.5 实现自定义的信号与槽函数,更新显示播放内容
/****************************************************
* 函数原型:void updateShowPlayListRow(int row)
* 函数功能:更新显示列表行的槽函数
* 根据播放内容列表的行改变更新显示列表的行
* 播放内容列表 0 行对应播放列表第一行
*****************************************************/
void Widget::updateShowPlayListRow(int row)
{
showPlayList->setCurrentRow(row+1);
//更新歌曲标题
//内容列表 改变, 歌曲名更新
updateSongTitleSlot();
}
//内容列表 改变, 歌曲名更新槽函数
void Widget::updateSongTitleSlot()
{
//当前项的文本
QString name = showPlayList->currentItem()->text();
QString str = "正在播放: " + name;
ui->songNameLb->setText(str);
}
下一首原理一样。
11.3 自动切换
当一首歌曲播放完成之后,要根据当前的播放模式进行相应的设置。
11.3.1 关联槽函数
connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinishedSlot()));
11.3.2 实现槽函数
void Widget::onPlayProcessFinishedSlot()
{
//定时器关闭
timer->stop();
playBtnState = false;
//更新播放暂停按钮
switch(playBtnState)
{
case true:
ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/暂停.png);"
"border-radius:10px;"
);
break;
case false:
ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/播放.png);"
"border-radius:10px;"
);
break;
}
if(ui->playProgressSlider->value() != ui->playProgressSlider->maximum())
{
return;
}
//如果 if 语句不成立,则说明,一首歌曲播放完成,而不是播放到一半点击下一首
//qDebug() << "一首歌曲播放完成.......";
//一首歌曲播放完成之后,根据播放模式选择要播放的音乐
switch (playModel)
{
case ListPlay: //顺序播
if(playIndex == playListString.count()-1)
{
//播放滑条清空。。。。。。
ui->playProgressSlider->setValue(0);
playState = false; //播放当前播放的内容,则停止播放
ui->songNameLb->setText("无歌曲");//显示无歌曲名
//当前时间和总共时间清零
ui->currentTimeLb->setText("00:00");
ui->totleTimeLb->setText("00:00");
//如果点击播放,默认播放的是第一首歌曲
playIndex = 0;
//设置当前行为第行
showPlayList->setCurrentRow(playIndex);
return;
}
playIndex++;
break;
case SingleSongOnce: //单曲一次
//播放当前播放的内容,则停止播放
ui->playProgressSlider->setValue(0);
ui->songNameLb->setText("无歌曲");//显示无歌曲名
//当前时间和总共时间清零
ui->currentTimeLb->setText("00:00");
ui->totleTimeLb->setText("00:00");
playState = false; //点击播放的时候,可以继续以当前的内容进行播放
return;
case SingleSongLoop: //单曲循环
break;
case PlayListLoop: //循环播放
if(playIndex == playListString.count()-1)
{
playIndex = 0;
}
playIndex++;
break;
case RandomPlay: //随机播放
qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
playIndex = qrand() %(playListString.count()-1);
break;
}
playState = false; //点击下一首之后需要播放音乐
playBtnState = false; //无论之前是什么状态,点击下一首之后必须播放
updatePlayPauseBtnStateSlot();
//发送播放内容改变信号
emit playConcentChanged(playIndex);
}
12、快进快退
12.1 关联拖动滑块信号与槽
//快进快退拖动槽函数
connect(ui->playProgressSlider,SIGNAL(sliderMoved(int)),this,SLOT(updateSongSeekSlo
t(int)));
12.2 实现拖动滑块信号与槽
void Widget::updateSongSeekSlot(int seek)
{
disconnect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSl
ot()));//断开读取数据的槽,避免拖动时重新设置了滑块的值
moveSliderVal = seek; //记录滑块的值
}
12.3 关联松开滑块信号与槽
//快进快退松开槽函数
connect(ui->playProgressSlider,SIGNAL(sliderReleased()),this,SLOT(updateSongSeekRel
easedSlot()));
12.4 实现松开滑块信号与槽
void Widget::updateSongSeekReleasedSlot()
{
qDebug()<< "Released";
int seek = (moveSliderVal * 100) / tlength;//百分比的进度
playProcess->write("pause\n");
QString str = QString("seek ");
if(playProcess->isOpen())
{
QString buf;
buf.setNum(seek);
str += buf + " 1\n";
playProcess->write(str.toLocal8Bit());
}
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSlot()));
重新连接读取数据的槽
}
14.13 关闭音乐
1. 关闭事件
void Widget::closeEvent(QCloseEvent *event)
{
//点击部件的叉号的时候,会自动调用关闭事件函数
//在关闭事件函数里面做一次释放
//进程关闭
playProcess->close();
//清空音乐显示列表
showPlayList->clear();
//清空播放内容列表
playListString.clear();
//显示列表部件关闭
showPlayList->close();
//发送销毁信号
qDebug() << "关闭程序。。。。。。";
//emit musicDestroyed(true);
}
13、隐藏播放器
13.1 关联槽函数
connect(ui->hideBtn,SIGNAL(clicked(bool)),this,SLOT(hideMusicPlayerSlots()));
13.2 实现槽函数
void Widget::hideMusicPlayerSlots()
{
//设置显示列表状态
playListBtnState = true;
//更新显示列表状态
updatePlayFileListBtnStateSlots();
this->hide();
}
14、保存歌曲
用户对应用程序经常有这样的要求:要求它能记住它的
settings
,比如窗口大小,位置,一些别的设置,还有 一个经常用的,就是 recent files
,等等这些都可以通过
Qsettings
来实现。
当我们创建一个
Qsettings
的对象时,我们需要传递给它两个参数,第一个是你公司或者组织的名称,第二个事你的应用程序的名称。
14.1 定义Settings对象指针
QSettings *configIniWrite; //配置文件写指针
QSettings *configIniRead; //配置文件读指针
QSettings *configIniDelete; //配置文件删除指针
14.2 添加列表中保存歌曲
void Widget::getLocalFileSots()
{
…
configIniWrite = new QSettings("PlayList.ini", QSettings::IniFormat);
for(int i = 0; i < infoList.count(); i++)
{
…
//保存当前歌曲
configIniWrite->setValue("/song/"+ QString::number(i),
infoList[i].filePath());//保存歌曲列表
…
}
showPlayList->setCurrentRow(0);
playListBtnState = true;
showPlayList->show();
}
14.3 加载保存歌曲
打开列表保存的歌曲
—
写一个函数,在构造函数中调用
void Widget::loadPlayListSong()
{
//打开用户保存的歌曲列表
configIniRead = new QSettings("PlayList.ini", QSettings::IniFormat);
QIcon musicMap(QPixmap(":/music/resource/player/playerlist/音符 1.png"));
for(int i=0; ; ++i) //将所有的播放列表显示在列表控件中
{
//100 是写进的值,所以返回的值也是 100
if(configIniRead->value("/song/"+QString::number(i),100).toInt()!=100)
{
QString path =
configIniRead->value("/song/"+QString::number(i)).toString();
//媒体播放内容列表需要带路径的文件名
playListString << path;
QFileInfo fileInfo;
fileInfo = QFileInfo(path);
// QString fileName = fileInfo.fileName();//文件名带后缀
QString fileName = fileInfo.baseName();//文件名不带后缀
// QString fileSuffix = fileInfo.suffix();//文件后缀
//显示给用户的列表只需要显示文件名,并在显示列表前面加图标
QListWidgetItem *songNameList = new
QListWidgetItem(musicMap,fileName);
songNameList->setSizeHint(QSize(400,40));
showPlayList->addItem(songNameList);
}
else
{
break;
}
}
showPlayList->setCurrentRow(0);
}
15、删除歌曲
void Widget::deleteSongBtnSlots()
{
configIniDelete = new QSettings("PlayList.ini",QSettings::IniFormat);//打开播放
列表配置文件
int currentRow = showPlayList->currentRow();
if( currentRow >= 0)
{
for (int i=currentRow; ; i++) //删除配置文件的内容
{
if(configIniDelete->value("/song/"+QString::number(i+1),100).toInt() !=
100) //如果下一行存在播放文件
{
configIniDelete->setValue("/song/"+QString::number(i),configIniDelete->value("/song
/"+QString::number(i+1)).toString());
}
else
{
configIniDelete->remove("/song/"+QString::number(i));
break;
}
}
QListWidgetItem* item = showPlayList->takeItem(currentRow); //删除显示列表的
内容
delete item;
showPlayList->update(); //更新显示
playListString.removeAt(currentRow); //删除播放列表的内容
}
}
完成!!!