日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

QT音乐播放器(接入网易云API)

發(fā)布時(shí)間:2023/12/10 c/c++ 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QT音乐播放器(接入网易云API) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)現(xiàn)的功能

1.可以播放本地音樂(lè)
2.實(shí)現(xiàn)常用功能(上下曲,播放/暫停,顯示播放時(shí)長(zhǎng))
3.通過(guò)網(wǎng)易云API搜索歌曲


實(shí)現(xiàn)步驟

1.在pro文件里面添加multimedia庫(kù)和network庫(kù)
2.設(shè)計(jì)好自己的UI界面
3.添加自己需要的頭文件并定義自己需要的變量
4.打開(kāi)自己存放歌曲的目錄,將歌曲添加到歌曲列表然后進(jìn)行播放
5.通過(guò)信號(hào)與槽機(jī)制實(shí)現(xiàn)常用的功能
6.接入網(wǎng)易云API進(jìn)行歌曲搜索

ui界面展示


代碼模塊展示

添加本地文件

file = QFileDialog::getOpenFileName(this,"Open File","D:/Music","mp3 Files (*.mp3)");//打開(kāi)MP3文件,如果需要添加其余音頻文件,只需繼續(xù)添加過(guò)濾項(xiàng)即可playlist->addMedia(QUrl(file));//將自己需要的MP3文件添加入播放列表//以下是去掉前面的路徑并且追加顯示到plainTextEdit(將名字復(fù)制到另一個(gè)字符串)int fi=0,af=9;//fi為新字符串的開(kāi)始位置,af為歌曲名字的第一個(gè)位置(自己的路徑)QString s;//新字符串while(file[af]!='\0')將歌曲名字移動(dòng)到數(shù)組開(kāi)頭{s[fi]=file[af];fi++;af++;}s[fi]='\0';//添加字符串結(jié)束標(biāo)志ui->plainTextEdit->appendPlainText(s);//顯示到plainTextEdit

播放/暫停

//通過(guò)標(biāo)志位來(lái)實(shí)現(xiàn)播放與暫停 if(x==0) //如果是停止?fàn)顟B(tài)或暫停就播放 {player->play();x=1; //置1下一次點(diǎn)擊就會(huì)暫停 } else if(x==1) //如果是播放狀態(tài)就暫停 {player->pause(); x=0; //置0下一次點(diǎn)擊就會(huì)播放 }

下一曲

//點(diǎn)擊下一曲,如果當(dāng)前歌曲是最后一首歌曲,就跳到第一首歌,其余則直接跳到下一首int m_Value=playlist->currentIndex(); //當(dāng)前歌曲是第幾個(gè)int m_Amount=playlist->mediaCount(); //總歌曲數(shù)量if(m_Value<m_Amount) //判斷當(dāng)前歌曲是否為最后一首{m_Value=m_Value+1; //播放的位置+1playlist->setCurrentIndex(m_Value); //重新設(shè)置播放的位置player->play(); }else{m_Value=0;playlist->setCurrentIndex(m_Value); //跳到第一首player->play();}

上一曲與之類似

時(shí)間顯示

//通過(guò)槽函數(shù)實(shí)現(xiàn) void Widget::timechange(qint64 duration) {int secs = duration/1000; //全部秒數(shù)int mins = secs/60;//分secs = secs % 60;//秒QString str=QString::asprintf("%d:%d",mins,secs);//轉(zhuǎn)換為字符串ui->lcdNumber->display(str);//用lcdNumber進(jìn)行顯示 }

正在播放歌曲顯示

//通過(guò)信號(hào)與槽機(jī)制檢測(cè)文件是否變化 void Widget::onDurationChanged(qint64 duration) //文件時(shí)長(zhǎng)變化,更新當(dāng)前播放文件名顯示播放文件數(shù)據(jù)總大小的信號(hào), 它可以獲得文件時(shí)間長(zhǎng)度。 {ui->horizontalSlider->setMaximum(duration); //設(shè)置進(jìn)度條最大值 也就是歌曲時(shí)長(zhǎng) msint m_Value=playlist->currentIndex();//獲取當(dāng)前歌曲的位置QTextBlock textLine=doc->findBlockByNumber (m_Value) ;//獲取當(dāng)前文本中的一段QString str=textLine.text();//將獲取后的數(shù)據(jù)轉(zhuǎn)為字符串int fi=0,af=9;QString s;if(str[0]=='D')//判斷是否為本地文件(我的歌是在D盤里面的,所以第一個(gè)字符是D){while(str[af]!='\0'){s[fi]=str[af];fi++;af++;}s[fi]='\0';ui->lineEdit->setText(s);}elseui->lineEdit->setText(str); }

進(jìn)度條顯示

void Widget::onPositionChanged(qint64 position)//當(dāng)前文件播放位置變化,更新進(jìn)度顯示播放到什么位置的信號(hào), 參數(shù)是以毫秒來(lái)計(jì)算的。 {if(ui->horizontalSlider->isSliderDown())return;//如果手動(dòng)調(diào)整進(jìn)度條,則不處理ui->horizontalSlider->setSliderPosition(position);//設(shè)置進(jìn)度條的位置 }

搜索歌曲ID

void Widget::on_b_search_clicked() {ui->music_m->clear();QString str,s;s=ui->l_search->text();//獲取在搜索框輸入的數(shù)據(jù)str="http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={"+s+"}&type=1&offset=0&total=true&limit=1";//接入網(wǎng)易云API并且傳入需要搜索的數(shù)據(jù)和返回的數(shù)量QNetworkRequest request; //定義一個(gè)請(qǐng)求對(duì)象request.setUrl(str); //將請(qǐng)求格式設(shè)置給請(qǐng)求對(duì)象manager->get(request); //請(qǐng)求}

解析返回的數(shù)據(jù)

void Widget::databack(QNetworkReply *reply) {searchInfo=reply->readAll(); //讀取返回的全部數(shù)據(jù)QJsonParseError err; //錯(cuò)誤信息對(duì)象QJsonDocument json_recv = QJsonDocument::fromJson(searchInfo,&err);//將json文本轉(zhuǎn)換為 json 文件對(duì)象if(err.error != QJsonParseError::NoError) //判斷是否符合語(yǔ)法{qDebug() <<"搜索歌曲Json獲取格式錯(cuò)誤"<< err.errorString();return;}QJsonObject totalObject = json_recv.object();QStringList keys = totalObject.keys(); // 列出json里所有的keyif(keys.contains("result")) //如果有結(jié)果{ //在 json 文本中 {}花括號(hào)里面是QJsonObject對(duì)象, []方括號(hào)里面是QJsonArrayQJsonObject resultObject = totalObject["result"].toObject(); //就將帶 result 的內(nèi)容提取后轉(zhuǎn)換為對(duì)象QStringList resultKeys = resultObject.keys(); //保存所有keyif(resultKeys.contains("songs")) //如果 key 為songs ,代表找到了歌曲{QJsonArray array = resultObject["songs"].toArray();for(auto i : array) //開(kāi)始獲取歌曲中的信息{QJsonObject object = i.toObject();musicId = object["id"].toInt(); // 音樂(lè)idmusicDuration = object["duration"].toInt(); // 音樂(lè)長(zhǎng)度musicName = object["name"].toString(); // 音樂(lè)名mvId = object["mvid"].toInt(); // mvidQStringList artistsKeys = object.keys();if(artistsKeys.contains("artists")) //如果result中包含了 artists{QJsonArray artistsArray = object["artists"].toArray(); //將 artist 的內(nèi)容提取后保存for(auto j : artistsArray){QJsonObject object2 = j.toObject();singerName = object2["name"].toString(); // 歌手名}}if(artistsKeys.contains("album")) //包含了專輯{QJsonObject albumObjct = object["album"].toObject();albumName = albumObjct["name"].toString(); // 專輯名}ui->music_m->appendPlainText("音樂(lè)ID:"+QString::number(musicId));ui->music_m->appendPlainText("音樂(lè)名:"+musicName);ui->music_m->appendPlainText("歌手名:"+singerName);ui->music_m->appendPlainText("總時(shí)長(zhǎng):"+QString::number(musicDuration));ui->music_m->appendPlainText("專輯名:"+albumName);}}}QString url;url=QString("https://music.163.com/song/media/outer/url?id=%0").arg(musicId);//通過(guò)網(wǎng)網(wǎng)易云API傳入之前返回的歌曲的ID實(shí)現(xiàn)播放playlist->addMedia(QUrl(url)); //添加一音樂(lè)到播放列表中ui->plainTextEdit->appendPlainText(musicName); //用于顯示 }

遇到的問(wèn)題:

1.網(wǎng)易云的API(自己在網(wǎng)上找的)

有關(guān)評(píng)論 http://music.163.com/api/v1/resource/comments/R_SO_4_{歌曲ID}?limit=20&offset=0 limit:返回?cái)?shù)據(jù)條數(shù)(每頁(yè)獲取的數(shù)量),默認(rèn)為20,可以自行更改 offset:偏移量(翻頁(yè)),offset需要是limit的倍數(shù) type:搜索的類型歌單 https://music.163.com/api/playlist/detail?id={歌單ID} 網(wǎng)易云音樂(lè)每日推薦各種神奇歌單也是它的一大特色,我們可以利用這個(gè)api獲取歌單里的所有歌曲信息。用戶信息 https://music.163.com/api/v1/user/detail/{用戶ID}歌詞 https://music.163.com/api/song/lyric?id={歌曲ID}&lv=1&kv=1&tv=-1搜索結(jié)果 http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={搜索內(nèi)容}&type=1&offset=0&total=true&limit=20 limit:返回?cái)?shù)據(jù)條數(shù)(每頁(yè)獲取的數(shù)量),默認(rèn)為20,可以自行更改 offset:偏移量(翻頁(yè)),offset需要是limit的倍數(shù) type:搜索的類型 type=1 單曲 type=10 專輯 type=100 歌手 type=1000 歌單 type=1002 用戶 type=1004 MV type=1006 歌詞 type=1009 主播電臺(tái)歌手專輯 http://music.163.com/api/artist/albums/{歌手ID}?id={歌手ID}&offset=0&total=true&limit=10專輯信息 http://music.163.com/api/album/{專輯ID}?ext=true&id={專輯ID}&offset=0&total=true&limit=10歌曲信息 http://music.163.com/api/song/detail/?id={歌曲ID}&ids=%5B{歌曲ID}%5DMV http://music.163.com/api/mv/detail?id={MV的ID}&type=mp4

2.可能報(bào)的錯(cuò)

qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed 大致說(shuō),Qt模塊中是包含了OpenSSL庫(kù)的,但是這些庫(kù)不會(huì)自動(dòng)部署到應(yīng)用程序中。開(kāi)發(fā)人員希望使用SSL的同時(shí),它們的用戶也安裝了相關(guān)庫(kù)。或者確保在當(dāng)?shù)厥褂肧SL是經(jīng)過(guò)許可 可以安裝opssl解決doRender: Unknown error 0x80040218. 可能是因?yàn)闆](méi)有裝解碼組件可以去安裝一個(gè) LAVFilters: 也可能是因?yàn)椴シ诺囊魳?lè)是VIP音樂(lè)(播放VIP音樂(lè)就會(huì)報(bào)這個(gè)錯(cuò))

效果視頻單獨(dú)發(fā)布了(用的那個(gè)游戲盒子錄的屏,跳出來(lái)的文件夾沒(méi)有顯示)

源碼

widget.h

#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMediaPlayer> #include <QMediaPlaylist> #include <QList> #include <QMediaContent> #include <QTextBlock> #include <QTimer> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QJsonParseError> #include <QJsonObject> #include <QJsonArray> #include <QMessageBox>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void on_pushButton_2_clicked();void on_pushButton_clicked();void on_next_clicked();void on_up_clicked();void timechange(qint64 duration);void onDurationChanged(qint64 duration); void onPositionChanged(qint64 position); void on_b_search_clicked();void databack(QNetworkReply *reply);private:Ui::Widget *ui;QString durationTime;QString positionTime;QNetworkAccessManager* manager;QMediaPlayer *player;QMediaPlaylist *playlist;QString file;QTextDocument* doc;QTextBlock textLine;QString str;int i,x;int musicId,musicDuration,mvId;QString musicName,singerName,albumName;QByteArray searchInfo; }; #endif // WIDGET_H

widget.cpp

#include "widget.h" #include "ui_widget.h"#include <QFileDialog> #include <QDir> #include <QFile> #include <QLCDNumber> #include <QString> #include <QBrush>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setMinimumSize(600,600);this->setMaximumSize(600,600);//我固定了窗口的大小ui->music_m->setReadOnly(true);//將顯示信息的組件設(shè)置設(shè)置為只讀manager = new QNetworkAccessManager(this); //定義并實(shí)例化一個(gè)網(wǎng)絡(luò)管家ui->plainTextEdit->setReadOnly(true);//將顯示音樂(lè)列表的組件設(shè)置為只讀ui->lineEdit->setReadOnly(true);//將顯示正在播放音樂(lè)的組件設(shè)置為只讀this->setWindowTitle("QT播放器");//設(shè)置窗口標(biāo)題x=0;//初始化標(biāo)志位doc=ui->plainTextEdit->document () ; //文本對(duì)象player=new QMediaPlayer(this);playlist=new QMediaPlaylist(this);//初始化對(duì)象player->setMedia(playlist);//設(shè)置播放列表playlist->setPlaybackMode(QMediaPlaylist::Loop);設(shè)置播放模式//信號(hào)與槽機(jī)制進(jìn)行處理connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(timechange(qint64)));connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(onPositionChanged(qint64)));connect(player,SIGNAL(durationChanged(qint64)),this,SLOT(onDurationChanged(qint64)));connect(manager,SIGNAL(finished(QNetworkReply *)),this,SLOT(databack(QNetworkReply *)));}Widget::~Widget() {delete ui; }void Widget::on_pushButton_2_clicked() {file = QFileDialog::getOpenFileName(this,"Open File","D:/Music","mp3 Files (*.mp3)");//打開(kāi)文件playlist->addMedia(QUrl(file));//將選中的MP3文件添加到播放列表//將選中的文件去掉路徑后追加顯示到plainTextEditint fi=0,af=9;QString s;while(file[af]!='\0'){s[fi]=file[af];fi++;af++;}s[fi]='\0';ui->plainTextEdit->appendPlainText(s);}void Widget::on_pushButton_clicked() {if(x==0) //如果是停止?fàn)顟B(tài)或暫停就播放{player->play();x=1;}else if(x==1) //如果是播放狀態(tài)就暫停{player->pause();x=0;} }void Widget::on_next_clicked() {int m_Value=playlist->currentIndex();//當(dāng)前歌曲是第幾個(gè)int m_Amount=playlist->mediaCount(); //總歌曲數(shù)量if(m_Value<m_Amount){m_Value=m_Value+1;playlist->setCurrentIndex(m_Value);player->play();}else{m_Value=0;playlist->setCurrentIndex(m_Value);player->play();}}void Widget::on_up_clicked() {int m_Value=playlist->currentIndex();//當(dāng)前歌曲是第幾個(gè)int m_Amount=playlist->mediaCount(); //總歌曲數(shù)量if(m_Value>0){m_Value=m_Value-1;playlist->setCurrentIndex(m_Value);player->play();}else{m_Value=m_Amount-1;playlist->setCurrentIndex(m_Value);player->play();} } void Widget::timechange(qint64 duration) {int secs = duration/1000; //全部秒數(shù)int mins = secs/60;//分secs = secs % 60;//秒QString str=QString::asprintf("%d:%d",mins,secs);ui->lcdNumber->display(str); }void Widget::onDurationChanged(qint64 duration) //文件時(shí)長(zhǎng)變化,更新當(dāng)前播放文件名顯示播放文件數(shù)據(jù)總大小的信號(hào), 它可以獲得文件時(shí)間長(zhǎng)度。 {ui->horizontalSlider->setMaximum(duration); //設(shè)置進(jìn)度條最大值 也就是歌曲時(shí)長(zhǎng) msint m_Value=playlist->currentIndex();QTextBlock textLine=doc->findBlockByNumber (m_Value) ; // 文本中的一段QString str=textLine.text();int fi=0,af=9;QString s;if(str[0]=='D'){while(str[af]!='\0'){s[fi]=str[af];fi++;af++;}s[fi]='\0';ui->lineEdit->setText(s);}elseui->lineEdit->setText(str); } void Widget::onPositionChanged(qint64 position)//當(dāng)前文件播放位置變化,更新進(jìn)度顯示播放到什么位置的信號(hào), 參數(shù)是以毫秒來(lái)計(jì)算的。 {if(ui->horizontalSlider->isSliderDown())return;//如果手動(dòng)調(diào)整進(jìn)度條,則不處理ui->horizontalSlider->setSliderPosition(position); }void Widget::on_b_search_clicked() {ui->music_m->clear();QString str,s;s=ui->l_search->text();str="http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={"+s+"}&type=1&offset=0&total=true&limit=1";QNetworkRequest request; //定義一個(gè)請(qǐng)求對(duì)象request.setUrl(str); //將請(qǐng)求格式設(shè)置給請(qǐng)求對(duì)象manager->get(request); //請(qǐng)求} void Widget::databack(QNetworkReply *reply) {searchInfo=reply->readAll();QJsonParseError err; //錯(cuò)誤信息對(duì)象QJsonDocument json_recv = QJsonDocument::fromJson(searchInfo,&err);//將json文本轉(zhuǎn)換為 json 文件對(duì)象if(err.error != QJsonParseError::NoError) //判斷是否符合語(yǔ)法{qDebug() <<"搜索歌曲Json獲取格式錯(cuò)誤"<< err.errorString();return;}QJsonObject totalObject = json_recv.object();QStringList keys = totalObject.keys(); // 列出json里所有的keyif(keys.contains("result")) //如果有結(jié)果{ //在 json 文本中 {}花括號(hào)里面是QJsonObject對(duì)象, []方括號(hào)里面是QJsonArrayQJsonObject resultObject = totalObject["result"].toObject(); //就將帶 result 的內(nèi)容提取后轉(zhuǎn)換為對(duì)象QStringList resultKeys = resultObject.keys(); //保存所有keyif(resultKeys.contains("songs")) //如果 key 為songs ,代表找到了歌曲{QJsonArray array = resultObject["songs"].toArray();for(auto i : array) //開(kāi)始獲取歌曲中的信息{QJsonObject object = i.toObject();musicId = object["id"].toInt(); // 音樂(lè)idmusicDuration = object["duration"].toInt(); // 音樂(lè)長(zhǎng)度musicName = object["name"].toString(); // 音樂(lè)名mvId = object["mvid"].toInt(); // mvidQStringList artistsKeys = object.keys();if(artistsKeys.contains("artists")) //如果result中包含了 artists{QJsonArray artistsArray = object["artists"].toArray(); //將 artist 的內(nèi)容提取后保存for(auto j : artistsArray){QJsonObject object2 = j.toObject();singerName = object2["name"].toString(); // 歌手名}}if(artistsKeys.contains("album")) //包含了專輯{QJsonObject albumObjct = object["album"].toObject();albumName = albumObjct["name"].toString(); // 專輯名}ui->music_m->appendPlainText("音樂(lè)ID:"+QString::number(musicId));ui->music_m->appendPlainText("音樂(lè)名:"+musicName);ui->music_m->appendPlainText("歌手名:"+singerName);ui->music_m->appendPlainText("總時(shí)長(zhǎng):"+QString::number(musicDuration));ui->music_m->appendPlainText("專輯名:"+albumName);}}}QString url;url=QString("https://music.163.com/song/media/outer/url?id=%0").arg(musicId);playlist->addMedia(QUrl(url)); //添加返回的音樂(lè)到播放列表中ui->plainTextEdit->appendPlainText(musicName); //用于顯示 }

總結(jié)

以上是生活随笔為你收集整理的QT音乐播放器(接入网易云API)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。