解决方案

嵌入式 QT 基于mplayer的音乐播放器

seo靠我 2023-09-23 04:24:23

1、实现功能

2、音乐播放界面

2.1 界面程序 

2.1.1 界面控制初始化

2.1.2 控件风格程序

3、 歌曲列表界面

3.1.1 在 widget.h 定义 QListWidge 对象指针

3.1.2 在 mSEO靠我emberInit 函数中添加 QlistWidge 初始化

3.1.3 在 setMusicPlayStyle 函数中设置其风格

4、音乐播放功能的实现

4.1 获取本地歌曲

4.1.1 显示歌曲列表

5、QSEO靠我process 实现 MPlayer

5.1 QT使用进程

5.2  QProcess 调用 MPlayer 方法

6、Mplayer命令大全

7、实现播放和暂停功能 

7.1 播放器初始化

7.2 播放函数实现

7SEO靠我.3 播放按钮功能实现

8、获取总时间和当前时间

8.1 在 MaplayerInit 函数中添加相关槽函数

8.2 在开始播放槽函数发送获取总时间命令

8.3 在获取数据槽函数中获取总时间和当前时间

8.4 SEO靠我在定时器槽函数中发送获取当前时间命令

8.5  在 playMusic 函数中启动定时器

8.6 在 updatePlayPauseBtnStateSlot 函数中添加定时器开关

9、双击播放功能

9.1 关SEO靠我联信号与槽

9.2 编写槽函数

10、音量设置

10.1 关联信号与槽

10.2 实现槽函数

11、歌曲切换

11.1 播放模式设置

11.1.1 使用枚举定义播放模式(类内定义枚举)

11.1.2 关联信号与槽

11SEO靠我.1.3 实现槽函数

11.2 上一曲

11.2.1 关联信号与槽

11.2.2 实现槽函数

11.2.3 槽函数发送自定义播放内容

11.2.4 关联自定义信号与槽

11.2.5 实现自定义的信号与槽函数,更新SEO靠我显示播放内容

11.3 自动切换

11.3.1  关联槽函数

11.3.2  实现槽函数

12、快进快退

12.1 关联拖动滑块信号与槽

12.2 实现拖动滑块信号与槽

12.3 关联松开滑块信号与槽

12.4 实现SEO靠我松开滑块信号与槽

13、隐藏播放器

13.1 关联槽函数

13.2 实现槽函数

14、保存歌曲

14.1 定义Settings对象指针

14.2 添加列表中保存歌曲

14.3 加载保存歌曲

15、删除歌曲

1、实现功能SEO靠我

音乐播放所实现的功能有: 1 ) 播放 / 暂停功能, 2 ) 上一首 / 下一首, 3 ) 设置音量, 4 ) 设置播放模式,SEO靠我 5 ) 双击歌曲列表的歌曲名可以播放音乐, 6 ) 播放音乐的时候可以显示要播放的歌曲名。 7 ) 显示当前播放的时间以及当前音乐的总时间。 SEO靠我 8 ) 滑动改变音乐的播放进度

2、音乐播放界面

其界面的布局是采用 ui 界面进行布局,没有使用程序代码进行布局的,在程序中,当然也可以使用 程序代码界面进行布局,此处部分是 ui 程序SEO靠我代码布局,播放列表使用程序布局。

2.1 界面程序 

2.1.1 界面控制初始化

//控件初始化 void Widget::memberInit() {QIcon scanIcSEO靠我on(QPixmap(":/music/resource/player/player_icon/open.png"));QIcon palyIcon(QPixmap(":/music/resourceSEO靠我/player/player_icon/list.png"));ui->scanLocalFileBtn->setIconSize(QSize(40,40));ui->scanLocalFileBtnSEO靠我->setIcon(scanIcon);ui->showPlayListBtn->setIconSize(QSize(40,40));ui->showPlayListBtn->setIcon(palySEO靠我Icon);QIcon sequenceIcon(QPixmap(":/music/resource/player/player_icon/列表循 环.png"));QIcon oncSEO靠我eIcon(QPixmap(":/music/resource/player/player_icon/单曲循环.png"));QIcon rangeIcon(QPixmap(":/music/resoSEO靠我urce/player/player_icon/随机播放.png"));QIcon onceSignle(QPixmap(":/music/resource/player/player_icon/单曲SEO靠我一次.png"));QIcon stepPlay(QPixmap(":/music/resource/player/player_icon/顺序播放.png"));ui->playModelCbox-SEO靠我>addItem(stepPlay,"顺序播放");ui->playModelCbox->addItem(onceSignle,"单曲一次");ui->playModelCbox->addItem(oSEO靠我nceIcon,"单曲循环");ui->playModelCbox->addItem(sequenceIcon,"循环播放");ui->playModelCbox->addItem(rangeIconSEO靠我,"随机播放");//音量滑条的范围 40~100 声音的范围(测试 40 以上有声音)ui->volumeSlider->setRange(0,100);//设置音量滑条的初始值为 70 SEO靠我 ui->volumeSlider->setValue(50); }

2.1.2 控件风格程序

void Widget::setMusicPlayStyle() { SEO靠我 //设置播放器背景图片 通过调色板实现QString musicBack = ":/music/resource/player/播放器背景.png";playerPalette.setBSEO靠我rush(QPalette::Background,QBrush(QPixmap(musicBack)));this->setPalette(playerPalette);this->setAutoFSEO靠我illBackground(true);//上一首ui->preSongBtn->setStyleSheet("border-image: url(:/music/resource/pSEO靠我layer/player_icon/prev.png);""border-radius:10px;");//下一首ui->nextSongBtn->setStyleSheet("border-imagSEO靠我e: url(:/music/resource/player/player_icon/next.png);""border-radius:10px;");//播放ui->playBtnSEO靠我->setStyleSheet("border-image: url(:/music/resource/player/player_icon/play.png);""border-raSEO靠我dius:10px;");//播放模式ui->playModelCbox->setStyleSheet("background: url(:/music/resource/player/播放 SEO靠我 器背景.png);""border: 1px solid gray;""border-radius:5px;""min-width: 6em;""font: 15px;""color: #FFSEO靠我FFFF;");//改变播放滑条和音量滑条的样式表ui->playProgressSlider->setStyleSheet("QSlider::groove:horizontal{border:0pSEO靠我x;height :4px;}""QSlider::subpage:horizontal{background:red;}""QSlider::addpage:horizontal{bSEO靠我ackground:lightgray;}""QSlider::handle:horizontal{background:white;width:10px;border-radius:5px;margSEO靠我in:- 3px 0px -3px 0px;}"); ui->volumeSlider->setStyleSheet( "QSlider::groove:horizonSEO靠我tal{border:0px;height:4px; }""QSlider::subpage:horizontal{background:red;}""QSlider::addpageSEO靠我:horizontal{background:lightgray;}""QSlider::handle:horizontal{background:white;width:10px;border-raSEO靠我dius:5px;margin:- 3px 0px -3px 0px;}");//扫描歌曲 播放列表 返回 关闭 透明ui->scanLocalFileBtn->setStyleSheSEO靠我et("background: transparent;""border: 1px solid gray;""border-radius:6px;""color: #FFFFFF;""font:16pSEO靠我x;""min-width: 4em;");ui->showPlayListBtn->setStyleSheet("background: transparent;""border: 1px soliSEO靠我d gray;""border-radius:6px;""color: #FFFFFF;""font:16px;""min-width: 4em;");ui->closeBtn->setStyleShSEO靠我eet("background: transparent;""border: 1px solid gray;""border-radius:6px;""color: #FFFFFF;""font:16SEO靠我px;""min-width: 4em;");ui->blackBtn->setStyleSheet("background: transparent;""border: 1px solid graySEO靠我;""border-radius:6px;""color: #FFFFFF;""font:16px;""min-width: 4em;");//歌曲名ui->songNameLb->setStyleSSEO靠我heet("font:18px;""color:#FFFFFF;");

3、 歌曲列表界面

 使用程序创建 QListWidget 控件来显示歌曲列表。

3.1.1 在 widget.h 定义 QListWiSEO靠我dge 对象指针

QListWidget *showPlayList;

3.1.2 在 memberInit 函数中添加 QlistWidge 初始化

//显示列表初始化showPlayList = new QSEO靠我ListWidget; //列表显示 --通过程序创建控制showPlayList->setMinimumSize(400,500);showPlayList->setMaximumSize(400,SEO靠我500);showPlayList->setWindowTitle("播放列表");showPlayList->setWindowIcon(QIcon(QPixmap(":/music/resourcSEO靠我e/image/music.png")));//设置显示列表显示的位置跟音乐部件的显示位置同一个高度,在音乐部件的后面,x 坐 标为音乐部件的宽度this->move(500,300)SEO靠我;showPlayList->move(this->width()+510,this->y()); playListBtnState = true; //false 隐藏,true 显SEO靠我示showPlayList->show();

3.1.3 在 setMusicPlayStyle 函数中设置其风格

//设置显示列表的背景showPlayList->setStyleSheet("QListWSEO靠我idget{color:#D4D4D4;""font:17px;""backgroundimage:url(:/music/resource/player/playerlist/播放器列表背景.pngSEO靠我);}");

4、音乐播放功能的实现

因为是基于 Linux 平台下实现 Qt 的音乐播放,如果利用 Qt 现有的提供的多媒体播放器 QMediaPlayer 进行实现的话, 只能是用于 Windows SEO靠我平台下的实现,是不支持 Linux 平台下, 因为 Qt5 多媒体播放使用QMediaPlayer,而 QMediaPlayer 使用 gstreamer 后端来播放媒体, gstreamer 又不能SEO靠我移植到 arm 。 所以最后决 定在 Qt5 上,使用 QProcess 直接调 MPlayer 的方式来实现音乐播放功能。 在这里将列举出该程序中使用到的核心功能。

4.1 获取本地歌曲

/******SEO靠我********************************************** * 函数原型:void getLocalFileSots() * 函数功能SEO靠我:获取本地音乐文件槽函数 *****************************************************/ void Widget::getSEO靠我LocalFileSots() {//获取选择的文件目录名QString fileNameDir = QFileDialog::getExistingDirectory(this,"选SEO靠我择音乐文件 ","../music");if(fileNameDir.isEmpty()){return;}//对目录进行扫描操作,需要目录类,利用目录路径构造目录类对象//1.利用 SEO靠我带路径的目录名 构造目录类对象QDir dir(fileNameDir);//2.编写 过滤的文件格式QStringList formatList;formatList << "*.mp3" << "SEO靠我*.mp4" << "*.wma";//3. 创建文件信息列表//QFileInfoList infoList;//4. 按照过滤的文件格式扫描文件,选择符合格式的文件infoList = dir.eSEO靠我ntryInfoList(formatList);if(infoList.isEmpty()){return;}//显示列表显示歌名的时候,前面加显示图标,显示图标的位置QIcon musicMap(SEO靠我QPixmap(":/music/resource/player/playerlist/音符 1.png"));for(int i = 0; i < infoList.count(); i++){//SEO靠我需要检测是否重复//媒体播放内容列表需要带路径的文件名playListString << infoList[i].filePath();//显示给用户的列表只需要显示文件名,并在显示列表前面加图标QLSEO靠我istWidgetItem *songNameList = new QListWidgetItem(musicMap,infoList[i].fileName()); SEO靠我songNameList->setSizeHint(QSize(400,40));showPlayList->addItem(songNameList);//打印文件路径 和文件名//qDebug()SEO靠我 << infoList[i].fileName(); //不带路径的文件名//qDebug() << infoList[i].filePath(); //带路径的文件名}showPlayList->SEO靠我setCurrentRow(0); }

4.1.1 显示歌曲列表

/****************************************************dddddd SEO靠我 * 函数原型:void updatePlayFileListBtnStateSlots() * 函数功能:更新显示文件列表的状态 * 该显示文件列表要么显SEO靠我示,要么被隐藏 * 说明: * playListBtnState == true 显示列表 * playListBtnState == false 隐藏SEO靠我列表 *****************************************************/ void Widget::updatePlayFilSEO靠我eListBtnStateSlots() {//跟以前状态相反playListBtnState = !playListBtnState;QIcon showIcon(QPixmap("SEO靠我:/music/resource/player/player_icon/列表.png"));QIcon hideIcon(QPixmap(":/music/resource/player/playerSEO靠我_icon/隐藏列表.png"));switch (playListBtnState){case true:showPlayList->show(); //显示ui->showPlayListBtn-SEO靠我>setIcon(hideIcon);break;case false:showPlayList->hide(); //隐藏ui->showPlayListBtn->setIcon(showIcon)SEO靠我;break;} }

5、Qprocess 实现 MPlayer

5.1 QT使用进程

 程序:

Widget::Widget(QWidget *parent) :QWidget(parent),uSEO靠我i(new Ui::Widget) {ui->setupUi(this);myProcess = new QProcess(this);connect(myProcess,SIGNALSEO靠我(readyRead()),this,SLOT(doSlotProcessReadyRead())); }void Widget::on_btnExec_clicked() SEO靠我 {QString cmd = ui->lEditCmd->text();QString arg = ui->lEditArg->text();QStringList arrayArg = argSEO靠我.split(" "); //获取所有的参数myProcess->start(cmd,arrayArg); }void Widget::doSlotProcessReadyRead()SEO靠我{while(!myProcess->atEnd()){//readLine 返回的是 QByteArray,转为 QString ,replace("\n","")去掉\nQString str =SEO靠我 QString(myProcess->readLine()).replace("\n","");ui->textEdit->append(str);} }

5.2  QProcess 调用 MSEO靠我Player方法

我们只需要 new 一个 QProcess, 然后通过 QProcess 的 start 方法启动 mplayer 线程即可.如下: process = new QSEO靠我Process(); QStringList args; args << "-slave"; // 使用 slave 模式 args << "-quiet"; // 不要输出冗余信息 _processSEO靠我->start("mplayer", args); // 启动该进程,并传入参数 args

 注意:这里的 mplayer 需要添加绝对路径, 也就是你当前 mplayer 所存放的位置

然后接下来这样,便SEO靠我可以启动 mplayer 。如果我们要控制 mplaer 呢,使用 QProcess 的 write 方法,往 mplayer 写入命令即可,比如如下: process->writSEO靠我e("pause\n");

 如果要读取 mplayer 发出来的消息呢,使用 QProcess 的 readLine 方法,方式如下:

_process->readLine(data,200);

这样便可以SEO靠我读取一行 mplayer 发送出来的信息,然后我们只需要解析这个 data 即可。

6、Mplayer命令大全

loadfile name     // 加载媒体文件 name volume 100 1 SEO靠我   // 设置音量,中间位音量的大小 0-100 seek 50 1          // 设置进度, 50 代表进度大小 ( 百分比 ) , 0-100 //0 is a relative seSEO靠我ek of +/- <value>                  seconds (default). //1 is a seek to <value> % in the movie. //2 iSEO靠我s a seek to an absolute position of <value> seconds. mute 1/0 // 静音开关 pause // 播放 / 暂停 get_time_lengSEO靠我th // 获取播放文件的总时间,以秒为单位 seek value // 定位, valu 为秒数 get_percent_pos // 获取播放的百分比 get_time_pos // 获取当前播放SEO靠我的位置,以秒为单位 get_file_name // 获取当前播放的媒体文件名 get_meta_album // 获取专辑 get_meta_artist // 获取艺术家 get_meta_comSEO靠我ment // 获取评论 get_meta_genre // 获取流派 get_meta_title // 获取标题 get_meta_year // 获取年份

7、实现播放和暂停功能 

7.1 播放器初始SEO靠我

在头文件 musicplay 中,添加相关成员的声明之后,然后在源文件中实现,首先是对播放器的初始化如下: //初始化播放器 void Widget::MaplaySEO靠我erInit() {//创建播放进程playProcess = new QProcess(this);playProcess->setProcessChannelMode(QProceSEO靠我ss::MergedChannels);program = "/usr/bin/mplayer"; //X86 架构下//program = "/usr/local/bin/mplayer"; //mSEO靠我player 命令路径,一定要正确,不然无法 播放 –ARM 架构playState = false; //播放状态playBtnState = false; //播放按钮状态 SEO靠我 playIndex = 0; //播放内容下标,跟显示列表的内容要保持一致 }

7.2 播放函数实现

void Widget::playMusic() {//如果SEO靠我没有加载播放内容playProcess->close();args.clear();args << "-slave"; //使用 slave 模式args << "-quiet"; //不要输出冗余信SEO靠我息args << playListString[playIndex];qDebug() << " playListString[playIndex]: " << playListString[playSEO靠我Index];QString str = "正在播放: " + showPlayList->currentItem()->text();ui->songNameLb->setText(str); //SEO靠我显示正在播放的音乐 playProcess->start(program,args); //开始播放playProcess->write("volume 70 1\n"); SEO靠我 playState = true; }

7.3 播放按钮功能实现

/**************************************************** SEO靠我 * 函数原型:void updatePlayPauseBtnStateSlot() * 函数功能:更新播放暂停按钮状态 ********************SEO靠我*********************************/ void Widget::updatePlayPauseBtnStateSlot() {playBSEO靠我tnState = !playBtnState;switch(playBtnState){case true:if(!playState) {playMusic();}else{playProcessSEO靠我->write("pause\n");}ui->playBtn->setStyleSheet("border-image: url(:/music/resource/player/plSEO靠我ayer_icon/暂停.png);""border-radius:10px;");break;case false:playProcess->write("pause\n");ui->playBtnSEO靠我->setStyleSheet("border-image: url(:/music/resource/player/player_icon/播放.png);""border-radiSEO靠我us:10px;");break; } }

8、获取总时间和当前时间

8.1 在 MaplayerInit 函数中添加相关槽函数

//初始化播放器 void WiSEO靠我dget::MaplayerInit() {//关联相关的信号,进程启动成功,出错,有数据可读等 connect(playProcess,SIGNAL(started(SEO靠我)),this,SLOT(onStartedSlot())); connect(playProcess,SIGNAL(error(QProcess::ProcessError)),thSEO靠我is,SLOT(onErrorSlot())) ; connect(playProcess,SIGNAL(readyReadStandardOutput()),thisSEO靠我,SLOT(onReadDataSlot())); connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFSEO靠我inishedSlot())); //创建定时器--定时器的主要功能, 就是用于定时获取当前音乐的播放时间, 然后进行 转换为当前的播放时间 timerSEO靠我 = new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(onTimeoutSlot())); }

8.2 在开始播放槽SEO靠我函数发送获取总时间命令

void Widget::onStartedSlot() {qDebug() << "准备播放";//获取播放文件的长度以毫秒为单位playProcess->wrSEO靠我ite("get_time_length\n"); }

8.3 在获取数据槽函数中获取总时间和当前时间

void Widget::onReadDataSlot() {whiSEO靠我le (playProcess->bytesAvailable()) {QByteArray arr = playProcess->readLine();QString str = QString::SEO靠我fromLocal8Bit(arr);if(str.contains("ANS_LENGTH")){//获取时间总长度qDebug() << "::"<<str;str.remove("\n");stSEO靠我r.remove("\r");str.remove("ANS_LENGTH=");qDebug() << "str = " << str ;int t = str.toDouble();int m =SEO靠我 t / 60;int s = t % 60;tlength = m * 60 + s;qDebug() << "tlength " << tlength;//设置播放进度的总数值ui->playPrSEO靠我ogressSlider->setMinimum(0);ui->playProgressSlider->setMaximum(tlength);ui->playProgressSlider->setSSEO靠我ingleStep(1);QString timeLength;timeLength.sprintf("%02d:%02d",m,s);ui->totleTimeLb->setText(timeLenSEO靠我gth);}if(str.contains("ANS_TIME_POSITION") ){//获取当前时间//qDebug() << "当前时间:: " << str ;str.remove("\n"SEO靠我);str.remove("\r");double t = QString(str.split("=").at(1)).toDouble();//显示当前时间int m = t / 60;int s SEO靠我= (int)(t+0.5) % 60; //四舍五入防止少时间QString timePos;timePos.sprintf("%02d:%02d",m,s);ui->currentTimeLb->SEO靠我setText(timePos);int now = (m * 60 + s);//double slider = now *100 /tlength;//设置播放进度当前滑条的值ui->playPrSEO靠我ogressSlider->setValue(now);}} }

8.4 在定时器槽函数中发送获取当前时间命令

void Widget::onTimeoutSlot() {SEO靠我//获取当前播放的位置,以秒为单位playProcess->write("get_time_pos\n"); }

8.5  在 playMusic 函数中启动定时器

void Widget::SEO靠我playMusic() {…..// 定时器开启 timer->start(100); }

8.6 在 updatePlayPauseBtnStateSloSEO靠我t函数中添加定时器开关

void Widget::updatePlayPauseBtnStateSlot() {playBtnState = !playBtnState;switch(pSEO靠我layBtnState){case true:if(!playState) {playMusic(); //第一次播放}else{playProcess->write("pause\n"); SEO靠我 timer->start(); →暂停后再次播放时启动定时器} …break;case false:playProcess->write("pause\n");timer->sSEO靠我top();→暂停播放时关闭定时器….break; }}

9、双击播放功能

9.1 关联信号与槽

//显示列表用户双击信号关联指定音乐文件的槽函数 connect(showPSEO靠我layList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedToPl ayerMusicSlots()));

9.SEO靠我2 编写槽函数

/**************************************************** * 函数原型:void loadMusicToPlayerSlSEO靠我ots() * 函数功能:加载指定音乐到播放列表槽函数 * 用户通过双击选择需要播放的音乐 ******************************SEO靠我***********************/ void Widget::doubleClickedToPlayerMusicSlots() {//获取显示列表的当前SEO靠我行int row = showPlayList->currentRow();playIndex = row;playState = false; //双击之后需要播放音乐playBtnState = SEO靠我false; //无论之前是什么状态,双击之后必须播放updatePlayPauseBtnStateSlot(); //更新播放暂停按钮—实现播放 }

10、音量设置

10.1 关联信号与SEO靠我

//音量改变信号 connect(ui->volumeSlider,SIGNAL(sliderMoved(int)),this,SLOT(setVolumeSlot(int)));

1SEO靠我0.2 实现槽函数

void Widget::setVolumeSlot(int volume) {QString str = QString("volume ");if(playProSEO靠我cess->isOpen()){QString buf;buf.setNum(volume); str += buf + " 1\n";//playProcess->write("voSEO靠我lume %d 1\n",volume);playProcess->write(str.toLocal8Bit());} }

11、歌曲切换

11.1 播放模式设置

11.1.1 使用枚举定SEO靠我义播放模式(类内定义枚举)

public:typedef enum{ListPlay = 0, //顺序播放SingleSongOnce = 1, //单曲一次SingleSongLoop = 2, /SEO靠我/单曲循环PlayListLoop = 3, //列表循环RandomPlay = 4, //随机播放 }PlayModel;

11.1.2 关联信号与槽

//模式选择关联 更新播放按钮槽SEO靠我函数 connect(ui->playModelCbox,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePlayMode SEO靠我 Slots(int)));

11.1.3 实现槽函数

/**************************************************** * 函数原型:voiSEO靠我d updatePlayModeSlots(int index) * 函数功能:更新播放模式,获取用户选择的模式 * 用户选择的模式跟系统的模式顺序关联 SEO靠我 *****************************************************/ void Widget::updatePlayModeSlots(intSEO靠我 index) {switch (index){case 0://顺序播放playModel = ListPlay;break;case 1://单曲一次playModel = SinSEO靠我gleSongOnce;break;case 2://单曲循环playModel = SingleSongLoop;break; case 3://循环播放playModel = PlSEO靠我ayListLoop;break;case 4://随机播放playModel = RandomPlay;break;} }

11.2 上一曲

11.2.1 关联信号与槽

//上一首 SEO靠我 connect(ui->preSongBtn,SIGNAL(clicked(bool)),this,SLOT(playPrevSongSlot()));

11.2.2 实现槽函数

void WiSEO靠我dget::playPrevSongSlot() { if(playIndex > 0){if(playModel == RandomPlay) //随机播放{qsraSEO靠我nd(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子playIndex = qrand() %(playListString.count()-SEO靠我1); //产生 playListString.count()-1 以内的随机数}else{playIndex--;}playState = false; //点击上一首之后需要播放音SEO靠我乐playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放updatePlayPauseBtnStateSlot();//发送播放内容改变信号emit playConSEO靠我centChanged(playIndex);}else{//回到最后一首if(playModel == RandomPlay) //随机播放{qsrand(QTime(0,0,0).msecsTo(SEO靠我QTime::currentTime()));//获取时间因子playIndex = qrand() %(playListString.count()-1); //产生 playLisSEO靠我tString.count()-1 以内的随机数}else{playIndex=playListString.count()-1; }playState = false; //点击上一SEO靠我首之后需要播放音乐playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放updatePlayPauseBtnStateSlot();//发送播放内容改变信号emitSEO靠我 playConcentChanged(playIndex);}

11.2.3 槽函数发送自定义播放内容

signals:void playConcentChanged(int index); //播放内SEO靠我容改变信号,播放内容改变,发送改变的 下标

11.2.4 关联自定义信号与槽

//媒体内容列表行改变(下一首、上一首、一首歌播放结束) 关联 显示列表行改变槽函数 connSEO靠我ect(this,SIGNAL(playConcentChanged(int)),this,SLOT(updateShowPlayListRow(int))) ; //SEO靠我双击当前行 播放内容改变(下一首、上一首、一首歌播放结束) 歌曲名更新 connect(showPlayList,SIGNAL(doubleClicked(QModelIndex)),SEO靠我this,SLOT(updateSongTitleSl ot()));

11.2.5 实现自定义的信号与槽函数,更新显示播放内容

/****************************SEO靠我************************ * 函数原型:void updateShowPlayListRow(int row) * 函数功能:更新显示列表行的槽SEO靠我函数 * 根据播放内容列表的行改变更新显示列表的行 * 播放内容列表 0 行对应播放列表第一行 ****************************SEO靠我*************************/ void Widget::updateShowPlayListRow(int row) {showPlayListSEO靠我->setCurrentRow(row+1);//更新歌曲标题//内容列表 改变, 歌曲名更新updateSongTitleSlot(); } //内容列表 改变, 歌SEO靠我曲名更新槽函数 void Widget::updateSongTitleSlot() {//当前项的文本QString name = showPlayList->curSEO靠我rentItem()->text();QString str = "正在播放: " + name;ui->songNameLb->setText(str); }

下一首原理一样。

11.3SEO靠我 自动切换

当一首歌曲播放完成之后,要根据当前的播放模式进行相应的设置。

11.3.1  关联槽函数

connect(playProcess,SIGNAL(finished(int)),this,SLOT(SEO靠我onPlayProcessFinishedSlot()));

11.3.2  实现槽函数

void Widget::onPlayProcessFinishedSlot() {//定时器关闭SEO靠我timer->stop();playBtnState = false;//更新播放暂停按钮switch(playBtnState) {case true:ui->playBtn->seSEO靠我tStyleSheet("border-image: url(:/music/resource/player/player_icon/暂停.png);""border-radius:1SEO靠我0px;");break;case false:ui->playBtn->setStyleSheet("border-image: url(:/music/resource/playeSEO靠我r/player_icon/播放.png);""border-radius:10px;");break;}if(ui->playProgressSlider->value() != ui->playPSEO靠我rogressSlider->maximum()){return;}//如果 if 语句不成立,则说明,一首歌曲播放完成,而不是播放到一半点击下一首//qDebug() << "一首歌曲播放完成...SEO靠我....";//一首歌曲播放完成之后,根据播放模式选择要播放的音乐switch (playModel){case ListPlay: //顺序播if(playIndex == playListStriSEO靠我ng.count()-1){//播放滑条清空。。。。。。ui->playProgressSlider->setValue(0);playState = false; //播放当前播放的内容,则停止播放SEO靠我ui->songNameLb->setText("无歌曲");//显示无歌曲名//当前时间和总共时间清零ui->currentTimeLb->setText("00:00");ui->totleTimSEO靠我eLb->setText("00:00");//如果点击播放,默认播放的是第一首歌曲playIndex = 0;//设置当前行为第行showPlayList->setCurrentRow(playInSEO靠我dex);return;}playIndex++;break;case SingleSongOnce: //单曲一次//播放当前播放的内容,则停止播放ui->playProgressSlider->sSEO靠我etValue(0); ui->songNameLb->setText("无歌曲");//显示无歌曲名//当前时间和总共时间清零ui->currentTimeLb->setText("SEO靠我00:00");ui->totleTimeLb->setText("00:00");playState = false; //点击播放的时候,可以继续以当前的内容进行播放return;case SinSEO靠我gleSongLoop: //单曲循环break;case PlayListLoop: //循环播放if(playIndex == playListString.count()-1){playIndeSEO靠我x = 0;}playIndex++;break;case RandomPlay: //随机播放qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));/SEO靠我/获取时间因子playIndex = qrand() %(playListString.count()-1);break;}playState = false; //点击下一首之后需要播放音乐playSEO靠我BtnState = false; //无论之前是什么状态,点击下一首之后必须播放updatePlayPauseBtnStateSlot();//发送播放内容改变信号 emit plaSEO靠我yConcentChanged(playIndex); }

12、快进快退

12.1 关联拖动滑块信号与槽

//快进快退拖动槽函数 connect(ui->playProgrSEO靠我essSlider,SIGNAL(sliderMoved(int)),this,SLOT(updateSongSeekSlo t(int)));

12.2 实现拖动滑块信号与槽

void SEO靠我Widget::updateSongSeekSlot(int seek) { disconnect(playProcess,SIGNAL(readyReadStandaSEO靠我rdOutput()),this,SLOT(onReadDataSl ot()));//断开读取数据的槽,避免拖动时重新设置了滑块的值moveSliderVal = seek; //记SEO靠我录滑块的值 }

12.3 关联松开滑块信号与槽

//快进快退松开槽函数 connect(ui->playProgressSlider,SIGNAL(sliderReleasSEO靠我ed()),this,SLOT(updateSongSeekRel easedSlot()));

12.4 实现松开滑块信号与槽

void Widget::updateSongSeekReSEO靠我leasedSlot() {qDebug()<< "Released";int seek = (moveSliderVal * 100) / tlength;//百分比的进度playPSEO靠我rocess->write("pause\n");QString str = QString("seek ");if(playProcess->isOpen()){QString buf;buf.seSEO靠我tNum(seek);str += buf + " 1\n";playProcess->write(str.toLocal8Bit()); } connect(playSEO靠我Process,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSlot())); 重新连接读取数据的槽 }SEO靠我 14.13 关闭音乐 1. 关闭事件 void Widget::closeEvent(QCloseEvent *event) {//点SEO靠我击部件的叉号的时候,会自动调用关闭事件函数//在关闭事件函数里面做一次释放//进程关闭playProcess->close();//清空音乐显示列表showPlayList->clear();//清空SEO靠我播放内容列表playListString.clear();//显示列表部件关闭showPlayList->close();//发送销毁信号qDebug() << "关闭程序。。。。。。";//emitSEO靠我 musicDestroyed(true); }

13、隐藏播放器

13.1 关联槽函数

connect(ui->hideBtn,SIGNAL(clicked(bool)),this,SLOSEO靠我T(hideMusicPlayerSlots()));

13.2 实现槽函数

void Widget::hideMusicPlayerSlots() {//设置显示列表状态playListSEO靠我BtnState = true;//更新显示列表状态updatePlayFileListBtnStateSlots(); this->hide(); }

14、保存歌曲

SEO靠我户对应用程序经常有这样的要求:要求它能记住它的 settings ,比如窗口大小,位置,一些别的设置,还有 一个经常用的,就是 recent files ,等等这些都可以通过 Qsettings 来实SEO靠我现。 当我们创建一个 Qsettings 的对象时,我们需要传递给它两个参数,第一个是你公司或者组织的名称,第二个事你的应用程序的名称。

14.1 定义Settings对象指针

QSetSEO靠我tings *configIniWrite; //配置文件写指针 QSettings *configIniRead; //配置文件读指针 QSettings *confSEO靠我igIniDelete; //配置文件删除指针

14.2 添加列表中保存歌曲

void Widget::getLocalFileSots() { … conSEO靠我figIniWrite = new QSettings("PlayList.ini", QSettings::IniFormat);for(int i = 0; i < infoList.count(SEO靠我); i++){…//保存当前歌曲configIniWrite->setValue("/song/"+ QString::number(i), infoList[i].filePathSEO靠我());//保存歌曲列表 … }showPlayList->setCurrentRow(0);playListBtnState = true; showPlayListSEO靠我->show(); }

14.3 加载保存歌曲

打开列表保存的歌曲 — 写一个函数,在构造函数中调用 void Widget::loadPlayListSong() SEO靠我 {//打开用户保存的歌曲列表configIniRead = new QSettings("PlayList.ini", QSettings::IniFormat); QIcSEO靠我on musicMap(QPixmap(":/music/resource/player/playerlist/音符 1.png"));for(int i=0; ; ++i) //将所有的播放列表显示SEO靠我在列表控件中{ //100 是写进的值,所以返回的值也是 100if(configIniRead->value("/song/"+QString::number(i),100).toISEO靠我nt()!=100){QString path = configIniRead->value("/song/"+QString::number(i)).toString();//媒体播SEO靠我放内容列表需要带路径的文件名playListString << path;QFileInfo fileInfo;fileInfo = QFileInfo(path);// QString fileNaSEO靠我me = fileInfo.fileName();//文件名带后缀QString fileName = fileInfo.baseName();//文件名不带后缀// QString fileSuffSEO靠我ix = fileInfo.suffix();//文件后缀//显示给用户的列表只需要显示文件名,并在显示列表前面加图标QListWidgetItem *songNameList = new SEO靠我 QListWidgetItem(musicMap,fileName);songNameList->setSizeHint(QSize(400,40));showPlayList->addItemSEO靠我(songNameList);}else{break;}}showPlayList->setCurrentRow(0); }

15、删除歌曲

void Widget::deleteSongSEO靠我BtnSlots() {configIniDelete = new QSettings("PlayList.ini",QSettings::IniFormat);//打开播放 SEO靠我 列表配置文件int currentRow = showPlayList->currentRow();if( currentRow >= 0){for (int i=currentRow; ; SEO靠我i++) //删除配置文件的内容{if(configIniDelete->value("/song/"+QString::number(i+1),100).toInt() != 100SEO靠我) //如果下一行存在播放文件{configIniDelete->setValue("/song/"+QString::number(i),configIniDelete->value("/song SEO靠我 /"+QString::number(i+1)).toString()); }else{configIniDelete->remove("/song/"+QStringSEO靠我::number(i));break;}}QListWidgetItem* item = showPlayList->takeItem(currentRow); //删除显示列表的 内SEO靠我容delete item;showPlayList->update(); //更新显示playListString.removeAt(currentRow); //删除播放列表的内容 SEO靠我} }

完成!!!

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2