基於Qt的網路音樂播放器,實現歌詞滾動顯示!QT還是好用的呀
1.思路和效果圖
先說一下大體思路:
json解析出來的lyrics歌詞(字串形式:[00:18.26]畢竟我們深愛過\r\n[00:21.74]有你陪的日子裡)中每句和每句之間有\n,所以我們利用這個換行符標識來分割字串,放在list中,這樣,我們得到的每一個字串都是時間戳+歌詞的形式,接下來,我們再繼續解析單個字串,用Qmap<int,QString>來儲存,時間作為鍵值,歌詞作為值,這樣就構成了時間對應歌詞的形式,然後通過QMediaPlayer類中positionChanged(qint64 duration)訊號呼叫槽函式onDurationChanged(qint64 duration)來顯示歌詞,positionChanged訊號會返回當前歌曲的進度,這個進度是毫秒級別的,將返回的時間與map的鍵值做對比,從而在適當的時間顯示對應的歌詞,歌詞用Label顯示。大體思路就是這樣,然後具體實現的時候,還是有許多細節需要注意的,遇到再說,還有就是上面提到的函式等等,在前面的文章中已經建立,下面的程式碼是直接寫實現,如果不知道在哪裡寫,可檢視前面幾篇文章。
2.歌詞的解析與儲存
mainwindow.h
//類成員 QMap<int,QString> lrcMap;
mianwindow.cpp
if (valuedataObject.contains("lyrics")) //lrc { QJsonValue play_url_value = valuedataObject.take("lyrics"); if (play_url_value.isString()) { QString play_lrcStr = play_url_value.toString(); if (play_urlStr != "") { if (play_lrcStr != "") { //將整個歌詞給s QString s = play_lrcStr; // s1 用列表的形式儲存每一句歌詞 QStringList s1 = s.split("\n"); for (int i = 3; i < s1.size() - 1; i++) { QString ss1 = s1.at(i); //歌詞中開頭有一些是無意義的字元,用正則表示式判斷,只儲存包含有時間戳的字串。 QRegExp ipRegExp = QRegExp("\\[\\d\\d\\S\\d\\d\\S\\d\\d\\]"); //若包含則返回flase bool match = ipRegExp.indexIn(ss1); if (match == false) { //時間解析格式(分*60+秒)*100+釐秒 int s_1 = ss1.mid(1, 2).toInt(); //分 int s_2 = ss1.mid(4, 2).toInt(); //秒 int s_3 = ss1.mid(7, 2).toInt(); //釐秒 int s_count = (s_1 * 60 + s_2) * 100 + s_3; //規定寫法 int lrctime = s_count; QString lrcstr = ss1.mid(10); //用Qmap來儲存 lrcMap.insert(lrctime, lrcstr); } } } else { //沒有歌詞; } } } }
由於json返回的歌詞裡面的時間表示是[02:12.85](.後面的數字表示85/100秒)這種形式,而positionChanged返回的是以毫秒的形式,為了能夠做對比,我們規定一種通用的表示方法:
時間解析格式(分*60+秒)*100+釐秒,這個釐秒就是小數點後面的數。
3.onDurationChanged()
void MainWindow::onPositionChanged(qint64 position) { //時間標籤得法 //(分*60+秒)*100+釐秒 int pos = position/10; QMap<int, QString>::iterator iter = lrcMap.begin(); while (iter != lrcMap.end()) { if(pos-50<=iter.key()&& pos+50>=iter.key()) { int j=0; if(iter != lrcMap.begin()) { iter--; ui->label_20->setText(iter.value()); j++; } if(iter != lrcMap.begin()) { iter--; ui->label_19->setText(iter.value()); j++; } if(iter != lrcMap.begin()) { iter--; ui->label_6->setText(iter.value()); j++; } for(;j>0;j--) { iter++; } //中間 ui->label_21->setText(iter.value()); iter++; if(iter != lrcMap.end()) { ui->label_22->setText(iter.value()); } else { ui->label_22->setText(""); return; } iter++; if(iter != lrcMap.end()) { ui->label_23->setText(iter.value()); } else { ui->label_23->setText(""); return; } iter++; if(iter != lrcMap.end()) { ui->label_24->setText(iter.value()); } else { ui->label_24->setText(""); return; } iter++; if(iter != lrcMap.end()) { ui->label_25->setText(iter.value()); } else { ui->label_25->setText(""); return; } iter++; if(iter != lrcMap.end()) { ui->label_26->setText(iter.value()); } else { ui->label_26->setText(""); return; } iter++; if(iter != lrcMap.end()) { ui->label_27->setText(iter.value()); } else { ui->label_27->setText(""); return; } } iter++; } }
label_21等10標籤用於顯示歌詞,label_21匹配當前時間顯示的歌詞,並且把該歌詞前面的歌詞和後面的歌詞分別傳送給其他對應的標籤。這樣就實現了動態效果。
4.總結
雖然程式碼很少,但是完成這個還是用了很長時間實現,反覆修改,反覆崩潰,沒實現前,覺得這個功能,要是能實現多好,實現了後又覺得自己寫的太簡單了,而且效果有一點僵硬,並沒有人家QQ 酷狗啊什麼,歌詞是慢慢往上滑,我這個是直接顯示,後面會研究研究怎麼滑動顯示,讓人看見更加平滑。學習就是這樣,來回不斷重複,對待問題的看法,邏輯的推理,思維的跳躍,從不會到實現,再到不滿足再實現。可執行檔案不是你的財富,修改過程中的經驗才是,我是花狗,一名苟且偷生的大專生,我們下篇見。
整個專案原始碼獲取加群哦:1136192749