关于歌词的显示,其实我的主要思想就是解析歌词部分的字符串。歌词显示分为两部分,一部分是播放器右侧的歌词显示以及下面的桌面歌词的显示。其中桌面歌词让我很难受,想了很久,后面看到一个大佬的一篇文章后才有了思路。
先看效果图:
其实就是解析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