关于歌词的显示,其实我的主要思想就是解析歌词部分的字符串。歌词显示分为两部分,一部分是播放器右侧的歌词显示以及下面的桌面歌词的显示。其中桌面歌词让我很难受,想了很久,后面看到一个大佬的一篇文章后才有了思路。
先看效果图:
其实就是解析lrc歌词字符串。lrc歌词分为两部分,前面部分是时间,后面一部分是歌词。得到时间和歌词,保存下来。我是用两个list保存的,其实后面一想,用map来保存其实更好。但是我没有改,你们可以改一下,用map来保存。
比如时间为00:40.11的时候歌词为:微笑在天上飞
在QMediaPlayer的positionChanged消息的相应函数里面。对比时间,现在播放的时间处于前面记录下来的时间的list中的哪两个之间,就显示相应的歌词。
桌面歌词:
桌面歌词其实就是重写paintevent函数,把文字绘制两遍,第一遍是原始颜色的歌词内容,第二遍是需要改变颜色的内容。就是使用有色的字绘制第二遍,把前面那一次绘制的一部分字遮住,就实现了这个效果。
看代码吧:
void lrc_widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setFont(font);//先绘制底层文字,作为阴影painter.setPen(Qt::white);painter.drawText(0,0,QFontMetrics(font).boundingRect(str1).width(),this->height()/2,Qt::AlignLeft,str1);painter.drawText(0,this->height()/2,QFontMetrics(font).boundingRect(str2).width(),this->height()/2,Qt::AlignLeft,str2);//设置歌词遮罩if(isFirst){painter.setPen(QPen(linearGradient,0));if(Proportion != 0){painter.drawText(0,0,QFontMetrics(font).boundingRect(str1).width()*(lrci/double(Proportion)),this->height()/2,Qt::AlignLeft,str1);}}else{painter.setPen(QPen(linearGradient,0));if(Proportion != 0){painter.drawText(0,this->height()/2,QFontMetrics(font).boundingRect(str2).width()*(lrci/double(Proportion)),this->height()/2,Qt::AlignLeft,str2);}}
}
其中str1为第一行歌词,str2为第二行歌词
QMediaPlayer的positionChanged消息的相应函数:
void Widget::on_player_position_change(qint64 position) //播放歌曲进度改变,改变时间显示,歌词改变
{ui->seekSlider->setValue(position);music_position = position;int h = music_position/3600000;int m = (music_position%3600000)/60000;int s = ((music_position%3600000)%60000)/1000;int ms = ((music_position%3600000)%60000)%1000;QString timestr;QTime time(h,m,s,ms);ui->now_time_label->setText(time.toString("hh:mm:ss"));QTime time2(h,m,s,ms);timestr = time2.toString("mm:ss");for(int i = 0;i < lrcTime.count();i++){if(time <= QTime::fromString(lrcTime.at(i),"mm:ss:zzz")){// i 为下一次唱的歌词QString mm1;QString ss1;QString zzz1;QString mm2;QString ss2;QString zzz2;if(lrcindex != i || i == 0){if(i == 0){myLrc_widget->setLabel_1_text(lrcStr.at(i));myLrc_widget->setLabel_2_text(lrcStr.at(i + 1));}else{if(nowIsFirst){myLrc_widget->setLabel_2_text(lrcStr.at(i));nowIsFirst = !nowIsFirst;}else{myLrc_widget->setLabel_1_text(lrcStr.at(i));nowIsFirst = !nowIsFirst;}}if(lrcindex <= 4) //前5行 直接下来 歌词不变{ui->Lrc_list->item(lrcindex)->setTextColor(Qt::red);for(int j = 0;j < lrcindex;j++){ui->Lrc_list->item(j)->setTextColor(Qt::black);}}else //超过5 通过改变每行显示的歌词来改变进度{for(int j = 0;j < 4;j++){ui->Lrc_list->item(j)->setText(lrcStr.at(lrcindex - 4 + j));}for(int j = 0;j < 6;j++){if(lrcindex + j < lrcStr.count()){ui->Lrc_list->item(4+j)->setText(lrcStr.at(lrcindex + j));}else{ui->Lrc_list->item(4+j)->setText("");}}}lrcindex = i;}if(i != 0){mm1 = QString(lrcTime.at(i)).split(":").at(0);ss1 = QString(lrcTime.at(i)).split(":").at(1);zzz1 = QString(lrcTime.at(i)).split(":").at(2);mm2 = QString(lrcTime.at(i - 1)).split(":").at(0);ss2 = QString(lrcTime.at(i - 1)).split(":").at(1);zzz2 = QString(lrcTime.at(i - 1)).split(":").at(2);int y = (mm1.toInt() - mm2.toInt())*60*1000 + (ss1.toInt() - ss2.toInt())*1000 + (zzz1.toInt() - zzz2.toInt());int x = (m - mm2.toInt())*60*1000 + (s - ss2.toInt())*1000 + (ms - zzz2.toInt());myLrc_widget->setProportion(x,y);}break;}}}
这就是所有的歌词显示部分的内容,可能有些地方说得不明白,如果大家哪里有问题的可以问,或者有什么更好的建议,我看到了就回复。大家互相学习。
上一篇:调用API解析数据
项目源码下载地址:https://download.csdn.net/download/qq_37141865/10703635
github:https://github.com/helloMrDjth/QtMusic
后面重新对界面进行了优化: