拖的太久,主要再上一篇文章中,新学习了相关知识,做了右键菜单,点击按钮动画切换窗口和播放时歌词颜色显示当前播放位置。
主要为了实现功能的展示,所以很多文件读取都直接采用了本地文件这种比较low的方式。对软件来说使用会很差,不过毕竟以实现为主,所以不再此考虑太多花里胡哨了。
点击动画效果
先上图对比下与qq音乐的样式
猛的一看好像就是点击按钮出现了一个新的窗口。其实这个动画效果唯一的特点就是,这个窗口是慢慢从底部滑动到顶部,滑动的时间是可以自己设置的。
动画效果设计思路
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。
欢迎交流。
我虽走的很慢,但我从不后退。—林肯