1. 程式人生 > >基於QT的網路音樂播放器(四)

基於QT的網路音樂播放器(四)

關於歌詞的顯示,其實我的主要思想就是解析歌詞部分的字串。歌詞顯示分為兩部分,一部分是播放器右側的歌詞顯示以及下面的桌面歌詞的顯示。其中桌面歌詞讓我很難受,想了很久,後面看到一個大佬的一篇文章後才有了思路。

先看效果圖:

在這裡插入圖片描述

其實就是解析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;
        }
    }

}

這就是所有的歌詞顯示部分的內容,可能有些地方說得不明白,如果大家哪裡有問題的可以問,或者有什麼更好的建議,我看到了就回復。大家互相學習。