首页 > 其他分享 >Qt编写网易云界面 (9) -----歌词界面、部分功能实现

Qt编写网易云界面 (9) -----歌词界面、部分功能实现

时间:2023-09-30 20:11:08浏览次数:59  
标签:界面 Qt void label ----- ui LyricWidget include setText

最近就是就是完成一些小功能,歌词界面,部分按钮的点击事件,歌词列表等;

效果如图:

视频页面

image-20230930195517822

歌单列表:

image-20230930200015308

歌词界面:

image-20230930195928753

点击歌曲详情页面:

image-20230930200110301

歌曲列表代码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界面就是简单实现了一下,详细界面也是简单实现点击事件,后续慢慢实现功能及美化。

标签:界面,Qt,void,label,-----,ui,LyricWidget,include,setText
From: https://www.cnblogs.com/dwinternet/p/17738163.html

相关文章

  • NO.6 Linux系统编程-备忘
    一、文件I/OFILE*fp指针(指向的结构体有三个重要的成员)文件描述符:通过文件描述可以找到文件的inode,通过inode可以找到对应的数据块文件指针:读和写共享一个文件指针,读或者写都会引起文件指针的变化文件缓冲区:读或者写会先通过文件缓冲区,主要目的是为了减少对......
  • DataFrame的代码构建-基于RDD方式
    方式一:#coding:utf8frompyspark.sqlimportSparkSessionif__name__=='__main__':#0.构建执行环境入口对象SparkSessionspark=SparkSession.builder.\appName("test").\master("local[*]").\getOr......
  • 202309301820_《Spring boot项目,继承mybatis-generator遇到的问题及解决》
     当配置到最后,双击右侧maventab,准备生成时,报红:1.“Loadingclass`com.mysql.jdbc.Driver'.Thisisdeprecated.Thenewdriverclassis`com.mysql.cj.jdbc.Driver'.ThedriverisautomaticallyregisteredviatheSPIandmanualloadingofthedriverclassisgen......
  • 2023-2024 20231324《计算机基础与程序设计》第1周学习总结
    这个作业属于哪个课程2023-2024-1《计算机基础与程序设计》这个作业的要求在哪里2023-2024-1计算机基础与程序设计第一周作业这个作业的目标快速浏览教材《计算机科学概论》,提出自己不懂或最想解决的问题并在期末回答作业正文本博客链接https://ww......
  • MAUI Blazor学习9-VS Code开发调试MAUI入门
     MAUIBlazor学习9-VSCode开发调试MAUI入门 MAUIBlazor系列目录MAUIBlazor学习1-移动客户端Shell布局-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习2-创建移动客户端Razor页面-SunnyTrudeau-博客园(cnblogs.com)MAUIBlazor学习3-绘制ECharts图表-Su......
  • 无涯教程-JavaScript - RIGHT函数
    描述RIGHT函数根据您指定的字符数返回文本字符串中的最后一个或多个字符。RIGHTB根据您指定的字节数返回文本字符串中的最后一个或多个字符。RIGHT适用于使用单字节字符集(SBCS)的语言,而RIGHTB适用于使用双字节字符集(DBCS)的语言。您计算机上的默认语言设置会影响返回值,如......
  • qemu源码分析(9)--Apple的学习笔记
    一, 前言本章节主要是再把GPIO创建的内容进行细化,搞明白gpio是否一个object,还和其它什么内容有关。二,分析 GPIOA,GPIOB等包括他们的寄存器都是object。每个对象都会再object_new的时候分配空间,比如GPIOA和GPIOB都有自己的空间。创建GPIOA,主要包括创建goio-peripheral类型及在conta......
  • 智能安全帽-GPS定位摄像头视频语音通话功能设计方案
    智能安全帽是一种集成了多种传感器和通信模块的创新设备。它内部包含陀螺仪、高度传感器、脱帽传感器、心率传感器、4G/5G通讯、GNSS定位、可选环境传感器以及语音播报系统等。这些功能使得智能安全帽能够实现人员定位、脱帽检测、生命体征监测、一键呼救、跌落监测、电子围栏......
  • numpy -- 数据分析三剑客
    博客地址:https://www.cnblogs.com/zylyehuo/NumPy(NumericalPython)是Python语言中做科学计算的基础库。重在于数值计算,也是大部分Python科学计算库的基础,多用于在大型、多维数组上执行的数值运算。开发环境anaconda集成环境:集成好了数据分析和机器学习中所需要的全......
  • python提取论文图片波形数据:pyautogui键盘移动鼠标,跨模块全局变量使用,cv2局部放大窗口
    最近写了一个python提取论文图片波形数据的脚本,代码如下。涉及新知识点:pyautogui键盘移动鼠标,跨模块全局变量使用,cv2局部放大窗口,matplotlib图片在pyQT5lable显示,坐标变换,多线程同时使用。搜索相关关键字去对应代码区看注释就可以了。gui窗口:1#-*-coding:utf-8-*-2......