Qt5学习 模仿qq音乐播放器样式(2)——点击动画效果+歌词颜色变换展示

拖的太久,主要再上一篇文章中,新学习了相关知识,做了右键菜单,点击按钮动画切换窗口和播放时歌词颜色显示当前播放位置。
主要为了实现功能的展示,所以很多文件读取都直接采用了本地文件这种比较low的方式。对软件来说使用会很差,不过毕竟以实现为主,所以不再此考虑太多花里胡哨了。

点击动画效果

先上图对比下与qq音乐的样式
qq音乐点击弹窗
qt点击弹窗
猛的一看好像就是点击按钮出现了一个新的窗口。其实这个动画效果唯一的特点就是,这个窗口是慢慢从底部滑动到顶部,滑动的时间是可以自己设置的。

动画效果设计思路

1、在主窗口内底部添加一个子窗口,窗口最小值为0,最大值为∞。样式可在上篇文章github连接查看
2、自定义动画效果类,但主要还是调用QPropertyAnimation类。
3、点击按钮之后,窗口位置根据设置的QRect发生改变。
相关代码

QMyanimation.h头文件

#ifndef QMYANIMATION_H
#define QMYANIMATION_H

#include <QObject>
#include <QWidget>
class QMyanimation : public QObject
{
    Q_OBJECT
public:
    explicit QMyanimation(QObject *parent = nullptr);
    void setAnimationWgt(QWidget* pParentWgt, QWidget* pSubWgt);
    void StartAnimation(bool bShow = true);
    void getAniamtionGeometry(QRect& RcBegin,QRect& RcEnd,bool IsShow);
signals:

public slots:

private:
    QWidget* m_ParentWgt;
    QWidget* m_SubWgt;
};

#endif // QMYANIMATION_H

QMyanimation.cpp源文件

#include "qmyanimation.h"
#include <QPropertyAnimation>
#include <QDebug>
QMyanimation::QMyanimation(QObject *parent)
    : QObject(parent)
{

}


void QMyanimation::setAnimationWgt(QWidget *pParentWgt, QWidget* pSubWgt)
{
    if(nullptr == pParentWgt || nullptr == pSubWgt)
    {
        return;
    }
    m_ParentWgt = pParentWgt;
    m_SubWgt = pSubWgt;
}

void QMyanimation::StartAnimation(bool bShow)
{
    if(nullptr == m_ParentWgt || nullptr == m_SubWgt)
    {
        return;
    }

    QPropertyAnimation* animation = new QPropertyAnimation(m_SubWgt, "geometry");
    QRect rcBegin;
    QRect rcEnd;
    getAniamtionGeometry(rcBegin, rcEnd, bShow);
    qDebug()<<rcBegin<<endl;
    qDebug()<<rcEnd<<endl;
    animation->setStartValue(rcBegin);
    animation->setEndValue(rcEnd);

    animation->start(QAbstractAnimation::DeleteWhenStopped);
}

void QMyanimation::getAniamtionGeometry(QRect &RcBegin, QRect &RcEnd, bool IsShow)
{
    if(nullptr == m_ParentWgt || nullptr == m_SubWgt)
    {
        return;
    }
    if(IsShow)
    {
        RcBegin = QRect(0,m_ParentWgt->height(),m_ParentWgt->width(),m_ParentWgt->height());
        RcEnd = QRect(0, 0, m_ParentWgt->width(),m_ParentWgt->height());
    }
    else
    {
        RcBegin = QRect(0, 0, m_ParentWgt->width(),m_ParentWgt->height());
        RcEnd = QRect(0,m_ParentWgt->height(),m_ParentWgt->width(),m_ParentWgt->height());
    }
}

在主窗口初始化时传入主窗口与子窗口(滑动窗口)位置即可。

void QMusicWidget::InitAnimation()
{
    m_nMusicAnimation = new QMyanimation(this);
    m_nMusicAnimation->setAnimationWgt(ui->widget, ui->MusicViewAnimation);
}

歌词播放颜色变换展示

话不多说,先上图看效果。QQ音乐,网易云等等歌词效果就没必要上图了,都见怪不怪了。
歌词颜色变换

歌词切换设计思路

歌词文件为普通的lrc文件,歌词格式为[00:00]xxxxxxxxx
读取文件内容对每一句歌词进行存储。并有个相关的Label展示。
还是为了功能实现,主要是思路的设计,文件都是写死的。

展示歌词的窗口
QMusicAnimation.h

#ifndef QMUSICANIMATION_H
#define QMUSICANIMATION_H

#include <QWidget>
#include <map>
#include <QLabel>
namespace Ui {
class QMusicAnimation;
}

class QMusicAnimation : public QWidget
{
    Q_OBJECT

public:
    explicit QMusicAnimation(QWidget *parent = nullptr);
    ~QMusicAnimation();

    void InitMusicAnimationStyle();
    void InitMusicLyric(std::string musicstr);
    void ParserLyirs(QString ParStr, std::string musicname);
    void InitLyircLabel(QString musicstr);
    void ChangeLyitcLabel(int posVal);
    void SetCurrentLyric(qint64 position);
signals:
    void sgnCloseMusicLryView(bool);
public slots:
    void OnSlotCloseMusicLryView();
private:
    Ui::QMusicAnimation *ui;
    std::map<std::string, std::map<int,std::string>> m_mLyricName;
    std::map<std::string, QLabel*> m_mLyircLabel;
    QString     m_sCurrentMusicName;
};

#endif // QMUSICANIMATION_H

我是采用了map来存储歌词与Label,如果你有更好的想法也可以尝试。

歌词跳转展示逻辑
QMusicAnimation.cpp

void QMusicAnimation::InitMusicLyric(std::string musicstr)
{
    QFile qssFile("/Users/liuyucheng/WorkSpace/Qt/Music_QQ/Resources/Lyric/" + QString::fromStdString(musicstr) + ".Lrc");//注意qss文件的保存路径
    qDebug()<<"/Users/liuyucheng/WorkSpace/Qt/Music_QQ/Resources/Lyric/" + QString::fromStdString(musicstr)<<endl;
    qssFile.open(QFile::ReadOnly);
    if(qssFile.isOpen())
    {
        QString qssStyle = QString::fromUtf8(qssFile.readAll());
        ParserLyirs(qssStyle, musicstr);
        qDebug()<<qssStyle<<endl;
    }
}
/*
解析歌词逻辑部分,按时间和歌词放入map进行保存
*/
void QMusicAnimation::ParserLyirs(QString ParStr, std::string musicname)
{
    QString playstr = ParStr;
    if(playstr != "")
    {
       QStringList s1 = playstr.split("\n");
       for(int i = 0;i < s1.size(); ++i)
       {
            QString s2 = s1.at(i);
            QRegExp ipRegExp = QRegExp("\\[\\d\\d\\S\\d\\d\\]");
            //若包含则返回flase
            bool match = ipRegExp.indexIn(s2);
            if (match == false)
            {
                //时间解析格式(分*60+秒)*100
                int s_1 = s2.mid(1, 2).toInt();      //分
                int s_2 = s2.mid(4, 2).toInt();      //秒
                //int s_3 = s2.mid(7, 2).toInt();      //厘秒
                int s_count = (s_1 * 60 + s_2) * 100; //+ s_3;
                int lrctime = s_count;
                QString lrcstr = s2.mid(7);
                qDebug()<<"lrctime = "<<lrctime<< "- - -" <<"lrcstr = "<<lrcstr<<endl;
                m_mLyricName[musicname].insert(std::map<int,std::string>::value_type(lrctime,lrcstr.toStdString()));
            }
       }
    }
}
//第一次加载过程中,直接展示在滑动窗口
void QMusicAnimation::InitLyircLabel(QString musicstr)
{
    m_sCurrentMusicName = musicstr;
    std::map<std::string, std::map<int,std::string>>::iterator mp1;
    QVBoxLayout* verticalLayout = new QVBoxLayout(ui->scrollAreaWidgetContents);
    for(mp1 = m_mLyricName.begin();mp1 != m_mLyricName.end();mp1++)
    {
        std::map<int,std::string>::iterator mp2 = mp1->second.begin();
        while(mp2 != mp1->second.end())
        {
            QLabel* lab = new QLabel(ui->scrollAreaWidgetContents);
            verticalLayout->addWidget(lab);
            lab->setText(QString::fromStdString(mp2->second));
            m_mLyircLabel[mp2->second] = lab;
            mp2++;
        }
    }
}
/*音乐播放过程,点击播放条会进行跳转,那么之前播放处的歌词颜色需要进行还原
可以查看整个源码,在其他地方会调用*/
void QMusicAnimation::ChangeLyitcLabel(int posVal)
{
    std::map<int,std::string>::iterator mp = m_mLyricName[m_sCurrentMusicName.toStdString()].begin();
    while(mp != m_mLyricName[m_sCurrentMusicName.toStdString()].end())
    {
        QPalette pe;
        pe.setColor(QPalette::WindowText,Qt::black);
        m_mLyircLabel[mp->second]->setPalette(pe);
        mp++;
    }
}
//设置歌词在播放过程中进行颜色变换切换
void QMusicAnimation::SetCurrentLyric(qint64 position)
{
    qint64 pos = position / 10;
    std::map<int,std::string>::iterator mp = m_mLyricName[m_sCurrentMusicName.toStdString()].begin();
    while(mp != m_mLyricName[m_sCurrentMusicName.toStdString()].end())
    {
        if(pos-50 <= mp->first && pos + 50 >= mp->first)
        {
            QPalette pe;
            pe.setColor(QPalette::WindowText,"#2eb372");
            m_mLyircLabel[mp->second]->setPalette(pe);
            if(mp != m_mLyricName[m_sCurrentMusicName.toStdString()].begin())
            {
                mp--;
            }
            if(mp != m_mLyricName[m_sCurrentMusicName.toStdString()].end())
            {
                QPalette pe;
                pe.setColor(QPalette::WindowText,Qt::black);
                m_mLyircLabel[mp->second]->setPalette(pe);
            }
            mp = m_mLyricName[m_sCurrentMusicName.toStdString()].end();
            break;
        }
        mp++;
    }
}

上边就是展示歌词的基本逻辑。目前还有一个小问题,在播放过程中,整个歌词窗口不会根据播放的时间自动向下滑动。这个有兴趣各位大佬可以随便动动手调整一下。

模仿QQ音乐播放器的一些基本功能都实现了。还有就是广告轮播设置和视频播放想尝试一下。关于歌词部分,还有个思路是通过调用各个播放器的API将音乐的json数据拿到进行解析保存,这个应该是一个比较合理的方法,我为了实现功能逻辑部分,做法比较low。

欢迎交流。

我虽走的很慢,但我从不后退。—林肯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值