Qt编写网易云界面 (9) -----歌词界面、部分功能实现
最近就是就是完成一些小功能,歌词界面,部分按钮的点击事件,歌词列表等;
效果如图:
视频页面
歌单列表:
歌词界面:
点击歌曲详情页面:
歌曲列表代码listform:
#ifndef LISTFORM_H
#define LISTFORM_H
#include <QVector>
#include <QWidget>
#include <QString>
namespace Ui {
class ListForm;
}
class ListForm : public QWidget
{
Q_OBJECT
public:
explicit ListForm(QWidget *parent = nullptr);
~ListForm();
void setdata();
QVector<QString> data;
int pos=0;
signals:
void mysig();
protected:
void leaveEvent(QEvent *event);
private slots:
void on_listWidget_currentRowChanged(int currentRow);
private:
Ui::ListForm *ui;
};
#endif // LISTFORM_H
listform.cpp:
#include "listform.h"
#include "ui_listform.h"
#include <QDebug>
ListForm::ListForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ListForm)
{
ui->setupUi(this);
}
void ListForm::setdata()
{
QStringList s;
for(int i=0;i<data.size();i++)
{
QString x=data[i];
QStringList a=x.split(".");
s.push_back(a[0]);
}
ui->listWidget->addItems(s);
}
ListForm::~ListForm()
{
delete ui;
}
void ListForm::leaveEvent(QEvent *event)
{
Q_UNUSED(event);
this->close();
}
void ListForm::on_listWidget_currentRowChanged(int currentRow)
{
pos = currentRow;
emit mysig();
}
歌曲界面的代码参考某个大佬的实现:
lyricwidget.h:
#ifndef LYRICWIDGET_H
#define LYRICWIDGET_H
#include<QWidget>
#include<QLabel>
#include<QFile>
#include<vector>
#include <QMouseEvent>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QPainter>
using namespace std;
//表示一行歌词(一个时间点+对应的歌词文本)
class LyricLine
{
public:
qint64 time;
QString text;
LyricLine(qint64 time, QString text):time(time), text(text){}
};
bool operator <(const LyricLine& A, const LyricLine& B);
namespace Ui {
class LyricWidget;
}
class LyricWidget : public QWidget
{
Q_OBJECT
//储存所有歌词
vector<LyricLine> lines;
public:
explicit LyricWidget(QWidget *parent = nullptr);
~LyricWidget();
//将歌词文件的内容处理为歌词结构的QList
bool process(QString filePath);
//根据时间找到对应位置的歌词
int getIndex(qint64 position);
//显示当前播放进度的歌词
void showcontent(qint64 position);
//根据下标获得歌词内容
QString getLyricText(int index);
//清空歌词Label
void clear();
LyricWidget* l;
QMediaPlaylist *playlist;
int pos;
QVector<QString> music;
void setlrc(LyricWidget* l,QMediaPlayer *player,QMediaPlaylist *playlist,int pos,QVector<QString> music);
//更新歌词
void updateSongLrc(qint64 position);
void updateSongLyclist();
protected:
//绘制背景函数
void paintEvent(QPaintEvent* event);
//鼠标按下
void mousePressEvent(QMouseEvent* event);
//鼠标移动
void mouseMoveEvent(QMouseEvent* event);
//鼠标释放
void mouseReleaseEvent(QMouseEvent* event);
private:
Ui::LyricWidget *ui;
QPoint last;
};
#endif // LYRICWIDGET_H
lyricwidget.cpp:
#include "LyricWidget.h"
#include "ui_lyricwidget.h"
#include <algorithm>
#include <QTextCodec>
#include<QDebug>
#include <QPainter>
LyricWidget::LyricWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LyricWidget)
{
ui->setupUi(this);
clear();//清空用于排版时的测试内容(.ui文件中)
ui->label_i->setStyleSheet("color:LightSkyBlue");
//首先去除自带的边框
this->setWindowFlag(Qt::FramelessWindowHint);
//背景透明
setAttribute(Qt::WA_TranslucentBackground);
}
LyricWidget::~LyricWidget()
{
delete ui;
}
void LyricWidget::setlrc(LyricWidget* l,QMediaPlayer *player,QMediaPlaylist *playlist,int pos,QVector<QString> music)
{
connect(player,&QMediaPlayer::positionChanged,this,&LyricWidget::updateSongLrc);//随时间变化歌词
l->show();
this->l=l;
this->pos=pos;
this->playlist=playlist;
this->music=music;
connect(playlist,&QMediaPlaylist::currentMediaChanged,this,&LyricWidget::updateSongLyclist);//歌曲变化就查找和提取歌词
}
void LyricWidget::updateSongLyclist()
{
int index=playlist->currentIndex();//获取当前位置
//歌名
QString songname_daihouzui=music[index];//提取在当前位置的文件名
qDebug() << songname_daihouzui;
QStringList songnamelist = songname_daihouzui.split(".");//QString字符串分割函数
QString songname=songnamelist[0];
qDebug()<<"歌词歌曲名:"<<songname;
QString lycpath="D:/mycode/qt_code/My_WYY/bin/music/" +songname+".lrc";
l->process(lycpath);
}
void LyricWidget::updateSongLrc(qint64 position)//随时间变化而变化显示歌词
{
l->showcontent(position);//更新歌词位置
}
void LyricWidget::mousePressEvent(QMouseEvent *event)
{
//获取title widget 的高度,这里固定为60px
int titleHeight = ui->layoutWidget->height();
if(event->y() <titleHeight)
{
last = event->globalPos(); //获取到按压的位置
}
}
void LyricWidget::mouseMoveEvent(QMouseEvent *event)
{
int titleHeight = ui->layoutWidget->height();
if(event->y() <titleHeight)
{
int dx = event->globalX() - last.x();
int dy = event->globalY() - last.y();
last = event->globalPos();
this->move(this->x()+dx,this->y()+dy);
}
}
void LyricWidget::mouseReleaseEvent(QMouseEvent *event)
{
int titleHeight = ui->layoutWidget->height();
if(event->y() <titleHeight)
{
int dx = event->globalX() - last.x();
int dy = event->globalY() - last.y();
this->move(this->x()+dx,this->y()+dy);
}
}
void LyricWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(rect(), QColor(0, 0, 0, 0)); // 使用透明色填充背景
// 其他绘制操作...
}
//重载比较(歌词按时间排序)
bool operator <(const LyricLine& A, const LyricLine& B)
{
return A.time<B.time;
}
bool LyricWidget::process(QString filePath)
{
QFile lyricFile(filePath);
//qDebug() << filePath<<"111";
lyricFile.open(QFile::ReadOnly);
//QString content(QString::fromLocal8Bit(lyricFile.readAll()));
QString content(lyricFile.readAll());
qDebug()<<"歌词\n"<<content;
lyricFile.close();
//先清空歌词
lines.clear();
const QRegExp rx("\\[(\\d+):(\\d+(\\.\\d+)?)\\]"); //用来查找时间标签的正则表达式
// 步骤1
int pos = rx.indexIn(content);//返回第一个匹配项的位置,如果没有匹配项则返回-1。
if (pos == -1) {
return false;
}
else {
int lastPos;//
QList<int> timeLabels;//时间标签
do {
// 步骤2
timeLabels << (rx.cap(1).toInt() * 60 + rx.cap(2).toDouble()) * 1000;
lastPos = pos + rx.matchedLength();//返回最后一个匹配字符串的长度,如果没有匹配则返回-1
pos = rx.indexIn(content, lastPos);
if (pos == -1) {
QString text = content.mid(lastPos).trimmed();
foreach (const int& time, timeLabels)
lines.push_back(LyricLine(time, text));
break;
}
// 步骤3
QString text = content.mid(lastPos, pos - lastPos);
if (!text.isEmpty()) {
foreach (const int& time, timeLabels)
lines.push_back(LyricLine(time, text.trimmed()));
timeLabels.clear();
}
}
while (true);
// 步骤4
stable_sort(lines.begin(), lines.end());//排序
}
if (lines.size()) {
return true;
}
return false;
}
int LyricWidget::getIndex(qint64 position)//获取歌词位置
{
if(!lines.size()){
return -1;//如果没歌词
}
else{
if(lines[0].time>=position){
return 0;
}
}
int i=1;
for(i=1;i<lines.size();i++){
if(lines[i-1].time<position && lines[i].time>=position){
return i-1;
}
}
return lines.size()-1;
}
void LyricWidget::showcontent(qint64 position)//显示当前播放进度的歌词
{
int index=getIndex(position);
if(index==-1){
//ui->label_3i->setText("");
//ui->label_2i->setText("");
ui->label_1i->setText("");
ui->label_i->setText(u8"当前歌曲无歌词");
ui->label_i1->setText("");
//ui->label_i2->setText("");
//ui->label_i3->setText("");
}else{
//ui->label_3i->setText(getLyricText(index-3));
//ui->label_2i->setText(getLyricText(index-2));
ui->label_1i->setText(getLyricText(index-1));
ui->label_i->setText(getLyricText(index));
ui->label_i1->setText(getLyricText(index+1));
//ui->label_i2->setText(getLyricText(index+2));
//ui->label_i3->setText(getLyricText(index+3));
}
}
QString LyricWidget::getLyricText(int index)//根据下标获得歌词内容
{
if(index<0 || index>=lines.size()){
return "";
}else{
//qDebug()<<"输出歌词:"<<lines[index].text;
return lines[index].text;
}
}
void LyricWidget::clear()
{
//ui->label_3i->setText("");
//ui->label_2i->setText("");
ui->label_1i->setText("");
ui->label_i->setText("");
ui->label_i1->setText("");
//ui->label_i2->setText("");
//ui->label_i3->setText("");
}
mv界面就是简单实现了一下,详细界面也是简单实现点击事件,后续慢慢实现功能及美化。