保姆级教学QT实战项目:基于QT的音乐播放器(一)


UI界面我就不细说了,可以自行参照设计,实现的功能有:

1.搜索网络歌曲,但是这个网络歌曲是自己模拟的服务器,与各大音乐软件服务器或者API什么的无关

2.歌词同步
3.随机播放,上一首,下一首,暂停播放。主要就是这些按钮控件。
 

最右边的按键就是歌曲列表与歌词页面的切换按钮

最左边的为随机播放功能开启和关闭



一、演示:

文件夹按钮为:有config文件配置,但是我这里没有进行显示,理由就是同上面显示的一样的操作,为了赶进度就没实现了,但是道理是一样的。

学完本项目可以了解一下QT中的:http请求,json分析,数据库操作,多线程操作,以及文件操作,专辑图像处理本程序并未实现,大家可以自行补充QT中的图像处理相关知识。



所以接下来我们先实现搜索网络歌曲部分。
以下是实现http功能的源代码
 

二、http请求部分(MusicHttp)

MusicHttp.h 

#include <QObject>
#include <QNetworkAccessManager>//处理网络请求和接收响应的一个核心类
#include <QUrl>//url地址
#include <QNetworkReply>//接收返回数据
#include <QNetworkRequest>//发送请求
#include <QFile>//文件操作,读取数据需要保存在文件
#include <QDebug>

class MusicHttp : public QObject
{
    Q_OBJECT
public:
    //枚举请求状态
    enum MusicHttpState{
        MusicFailHttp,
        MusicSuccessHttp,
    };
    explicit MusicHttp(const QString &filename,QObject *parent = nullptr);

    bool GetHttpState();
    void setFilename(const QString &value);
    void onGet(const QString& httpurl); 
    void onreadyRead();
    QByteArray onreadData();
    void onhandFinished();
    void onhandError(QNetworkReply::NetworkError code);

signals:
    void readyRead();
    void error();

public slots:

private:
    QString filename;//文件名
    QNetworkAccessManager* networkManager;//请求对象
    enum MusicHttpState httpstate;//判断请求成功还是失败
};

#endif // MUSICHTTP_H

MusicHttp.cpp 

/*
第一,我们要创建一个网络管理对象,用于发送和接收http请求
同时我们还需要一个文件,用于存放请求接受的数据,因为搜索一首歌可以有多个返回结果,所以每次都需要重新写入文件,我用的是
    if(QFile::exists(filename))
        QFile::remove(filename);
第二,我自己枚举了请求状态,成功或失败都应该进行处理,成功可以返回搜索结果,失败可以弹出对话框,比如说因为网络问题请求失败
第三,只要连接成功并且接收到数据,QNetworkReply会发出readyRead信号,但是如果文件太大,那会分几次发送,所以我连接了onreadyRead函数,对接受到的数据进行写入,只有当数据接收完,该类发送finished的时候我自定义一个readyRead信号,接受到自定义的信号然后对文件进行读取,所以有两个readyRead信号,不要搞混淆了。一个是自定义,一个是QNetworkReply的。不过该类在连接失败的时候也会发送finished信号,所以发送了一个自定义的错误信号,可以对该信号进行捕获做出对应的处理操作。
第四,可能onGet(const QString& httpurl),可能对这个存在不理解,为什么是这个参数,而且没有调用,但是我们是要根据按下搜索的回车键进行搜索,与其他类配合使用,所以先记下这个参数,往后其他类实现会提及。
第五,实际上我们得到的是json数据,但是这个json数据是我自己参照写的,需要对这个json进行分析,后面有类会对其进行分析,如果要得到真正的json文件需要用到爬虫,本人不会,所以只好自己仿制了。
第六,用到的QT中的类还比较简单,有需要的伙伴可以自行查看帮助手册
*/





#include "musichttp.h"

MusicHttp::MusicHttp(const QString &filename,QObject *parent) : 
    QObject(parent),filename(filename)
{
    networkManager = new QNetworkAccessManager(this);
    //将请求状态初始化为成功
    httpstate=MusicHttpState:: MusicSuccessHttp;
}

//发送请求部分
void MusicHttp::onGet(const QString& httpurl)
{
    if(QFile::exists(filename)){
        QFile::remove(filename);
    }
    //连接服务器的返回状态初始化为成功
    httpstate=MusicHttpState:: MusicSuccessHttp;
    
    //创建url对象,也就是设置url地址
    QUrl url(httpurl);
    //创建一个请求对象,用于发送请求
    QNetworkRequest request(url);
    //发送请求,返回一个reply对象
    //该返回对象接受到数据会发送readyRea信号
    QNetworkReply *reply = networkManager->get(request);
    connect(reply,&QNetworkReply::readyRead,this,&MusicHttp::onreadyRead);
    //数据发送完毕或者是请求失败,发出finished信号,处理该信号
    connect(reply,&QNetworkReply::finished,this,&MusicHttp::onhandFinished);

    //请求失败处理部分
    //对请求失败进行输出,输出失败原因
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),\
          this,SLOT(onhandError(QNetworkReply::NetworkError)));

}

//处理请求完成
void MusicHttp::onhandFinished()
{
    QNetworkReply *reply =(QNetworkReply *)this->sender();
    //如果不是请求失败,则发出readyRead信号,表示可以读取数据
    if(reply->error() == QNetworkReply::NoError){
        emit readyRead();
    }
    reply->deleteLater();
}

//处理请求失败
void MusicHttp::onhandError(QNetworkReply::NetworkError code)
{
    qDebug()<<"error code:"<<code;
    httpstate=MusicHttpState:: MusicFailHttp;
    emit error();
}

//处理接受到的数据
void MusicHttp::onreadyRead()
{
    //连接该槽函数的对象是局部变量,所以要先获取是谁发送的信号
    QNetworkReply *reply =(QNetworkReply *)this->sender();
    //读取数据写入缓冲区
    QByteArray data =reply->readAll();
    //准备一个文件,将缓冲区数据以追加的方式写入文件
    QFile file(filename);
    bool ok = file.open(QFile::WriteOnly|QFile::Append);
    if(!ok){
        qDebug()<<"fail open "<<filename<<"to write \n Error:"<<file.errorString();
        return;
    }
    file.write(data);
    file.close();
    return;
}

//对保存的数据进行读取
QByteArray MusicHttp::onreadData()
{
    QFile file(filename);
    bool ok = file.open(QFile::ReadOnly);
    if(!ok){
        qDebug()<<"fail open "<<filename<<"to Read \n Error:"<<file.errorString();
        return QByteArray();
    }
    QByteArray data = file.readAll();
    file.close();
    return data;
}

//构造函数
void MusicHttp::setFilename(const QString &value)
{
    filename = value;
}

//用户查询成功还是失败
bool MusicHttp::GetHttpState()
{
    return httpstate==MusicHttpState::MusicSuccessHttp ? true : false;
}

实现网络请求部分,接下来就是搜索功能实现部分了


三、搜索功能部分(MusicSearch)

准备一个json文件,以下是我自己仿的,仅供学习使用。filename:你瞒我瞒.json

MusicSearch.h

#ifndef MUSICSEARCH_H
#define MUSICSEARCH_H

#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonParseError>
#include <QJsonDocument>
#include "musichttp.h"
#include "musicinformation.h"


class MusicSearch : public QObject
{
    Q_OBJECT
public:
    explicit MusicSearch(QObject *parent = nullptr);
signals:
    showMusicInfo(const QVector<MusicInformation* > musicInfoList);
public slots:
    //搜索对应的歌曲名方法方法,
    void search(const QString& music);
    //读取歌曲文件
    void onreadyRead();
    //解析json数据
    void parseMusicJsonData(const QByteArray jsondata);
    //清空容器
    void clearMusicList();
private:
    MusicHttp* musicHttp;
    //创建容器,里面的类型为MusicInformation*,下一部分提及
    QVector<MusicInformation* > musicInfoList;
};

#endif // MUSICSEARCH_H

MusicSearch.cpp 

/*
第一,创建MusicHttp对象,可以使用里面的接口方法,当自定义的readyRead信号发出的时候,就可以对其进行读取分析,在MusicHttp部分说了,得到的是json数据。
第二,//实现搜索歌曲 void MusicSearch::search(const QString &music) 该函数主要是在搜索栏按下的时候调用,根据歌曲在服务器寻找对应的歌曲json文件,而我模拟的web服务器主要地址就是
http://localhost/QQ音乐下载/,也就是从这里开始找。
第三,这里我封装了一个MusicInfomation的类,主要是用于存储歌曲信息,这里还没有讲,如果不用也是一样的,自定义QString musicMp3Url,QString musicLrcUrl,...。添加这个类主要是可以创建一个对象,发生信号的时候把容器发送过去,再一个个在ui界面进行显示就比较方便
第四,注意json文件的错误信号,解析失败的时候要对其进行处理。
第五,当解析完所有的JSON数据,并且插入容器的时候,就可以发送信号,将容器发送过去,主界面进行捕获,就可以显示在ui界面上
*/






#include "musicsearch.h"

MusicSearch::MusicSearch(QObject *parent) : QObject(parent)
{
    musicHttp = new MusicHttp("music.json",this);
    //连接MusicHttp的readyRead信号,对其进行读取
    connect(musicHttp,&MusicHttp::readyRead,this,&MusicSearch::onreadyRead);
}

//实现搜索歌曲
void MusicSearch::search(const QString &music)
{
    QString httpurl = QString("http://localhost/QQ音乐下载/%1/%2.json").arg(music).arg(music);
    musicHttp->onGet(httpurl);
}

//获取从服务器返回的数据
void MusicSearch::onreadyRead()
{
    QByteArray data = musicHttp->onreadData();
    //对接收到的json文件进行解析
    parseMusicJsonData(data);
}

//解析json文件
void MusicSearch::parseMusicJsonData(const QByteArray jsondata)
{
    QJsonParseError jsonParseError;
    QJsonDocument musicDocument =QJsonDocument::fromJson(jsondata,&jsonParseError);
    if(musicDocument.isEmpty()){
        qDebug()<<"Fail to parse data:"<<musicDocument<<"Error:"<<jsonParseError.errorString();
        return ;
    }
    QJsonObject musicObject = musicDocument.object();
    QJsonArray musicArray = musicObject["list"].toArray();

    for(int i=0;i<musicArray.size();i++){
        MusicInformation* music = new MusicInformation;
        QJsonObject object = musicArray[i].toObject();
        QString musicName = object["musicName"].toString();
        QString albumName = object["albumName"].toString();
        QString duration =QString::number(object["duration"].toInt());
        QString musicPath = object["path"].toString();
        QString musicMp3 = object["mp3"].toString();
        QString musicLrc = object["lyric"].toString();

        music->musicName = musicName;
        music->albumName = albumName;
        music->duration = duration.toInt();
        music->musicLrcName = musicLrc;
        music->musicMp3Url = QString(music->bodyUrl+musicPath+"/"+musicMp3);
        music->musicLrcUrl = QString(music->bodyUrl+musicPath+"/"+musicLrc);
        music->musicAlbumUrl=QString(music->bodyUrl+musicPath+"/"+albumName+".jpg");
        //将得到的歌曲信息插入歌曲容器
        musicInfoList.append(music);
 
    }
    //发送信号,可以显示歌曲
    emit showMusicInfo(musicInfoList);
}

//清空歌曲列表容器
void MusicSearch::clearMusicList()
{
    qDeleteAll(musicInfoList.begin(), musicInfoList.end());
    musicInfoList.clear();
}


四、歌曲信息类,MusicInfomation 

/*
    这里没什么说的,就是一些成员变量,同时有QT自己生成的构造函数,可以根据自己需要添加成员变量,另外这里不仅有网络歌曲,后面还需要播放本地歌曲,所以就合在了一块儿.主要就是我服务器的基本路径,每个人都不同,这只是我从该路径开始而已
*/


#ifndef MUSICINFORMATION_H
#define MUSICINFORMATION_H

#include <QObject>
#include <QDebug>
#include <QString>

class MusicInformation : public QObject
{
    Q_OBJECT
public:
    explicit MusicInformation(QObject *parent = nullptr);

    //主地址,服务器基本路径
    QString bodyUrl="http://localhost/QQ音乐下载/";
    //歌曲文件夹地址
    QString musicUrl;
    //mp3地址
    QString musicMp3Url;
    //歌词地址
    QString musicLrcUrl;
    //专辑图片地址
    QString musicAlbumUrl;
    //歌曲名
    QString musicName;
    //专辑名
    QString albumName;
    //歌曲时长
    qint16 duration;
    //歌词名
    QString musicLrcName;
    //本地mp3地址
    QString musicLocalMp3Path;
    //本地歌词地址
    QString musicLocalLrcPath;
    //本地专辑地址
    QString musicLocalAlmPath;

    QString getMusicUrl() const;
    void setMusicUrl(const QString &value);
    
    QString getMusicMp3Url() const;
    void setMusicMp3Url(const QString &value);
    
    QString getMusicLrcUrl() const;
    void setMusicLrcUrl(const QString &value);
    
    QString getMusicAlbumUrl() const;
    void setMusicAlbumUrl(const QString &value);
    
    QString getMusicName() const;
    void setMusicName(const QString &value);
    
    QString getAlbumName() const;
    void setAlbumName(const QString &value);
    
    qint16 getDuration() const;
    void setDuration(const qint16 &value);
    
    QString getMusicLrcName() const;
    void setMusicLrcName(const QString &value);
    
    QString getMusicLocalMp3Path() const;
    void setMusicLocalMp3Path(const QString &value);
    
    QString getMusicLocalLrcPath() const;
    void setMusicLocalLrcPath(const QString &value);
    
    QString getMusicLocalAlmPath() const;
    void setMusicLocalAlmPath(const QString &value);
    
signals:
    
public slots:
    
private:
    
    
};

#endif // MUSICINFORMATION_H


 

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
好的,以下是Qt5.9.8保姆安装教程: 步骤一:下载安装包 在Qt官网上下载Qt5.9.8源代码包(qt-everywhere-src-5.9.8.tar.xz),下载完成后解压到你喜欢的目录下。 步骤二:安装依赖库 安装Qt5.9.8需要的依赖库,包括但不限于以下几个: sudo apt-get install build-essential sudo apt-get install libfontconfig1-dev sudo apt-get install libfreetype6-dev sudo apt-get install libx11-dev sudo apt-get install libxext-dev sudo apt-get install libxfixes-dev sudo apt-get install libxi-dev sudo apt-get install libxrender-dev sudo apt-get install libxcb1-dev sudo apt-get install libx11-xcb-dev sudo apt-get install libxcb-glx0-dev sudo apt-get install libxcb-keysyms1-dev sudo apt-get install libxcb-image0-dev sudo apt-get install libxcb-shm0-dev sudo apt-get install libxcb-icccm4-dev sudo apt-get install libxcb-sync-dev sudo apt-get install libxcb-xfixes0-dev sudo apt-get install libxcb-shape0-dev sudo apt-get install libxcb-randr0-dev sudo apt-get install libxcb-render-util0-dev sudo apt-get install libxcb-xinerama0-dev sudo apt-get install libxcb-xtest0-dev sudo apt-get install libgl1-mesa-dev sudo apt-get install libglu1-mesa-dev sudo apt-get install libssl-dev sudo apt-get install libpq-dev sudo apt-get install libmysqlclient-dev sudo apt-get install libsqlite3-dev sudo apt-get install unixodbc-dev sudo apt-get install libpng-dev sudo apt-get install libjpeg-dev sudo apt-get install libgif-dev sudo apt-get install libwebp-dev 步骤三:配置环境变量 打开终端,输入以下命令: sudo gedit ~/.bashrc 在文件末尾加入以下内容: export QTDIR=$YOUR_QT_PATH export PATH=$QTDIR/bin:$PATH export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH 其中,$YOUR_QT_PATH为你的Qt源码包所在的目录。 步骤四:编译安装 在终端中进入Qt源码包所在目录,输入以下命令: ./configure -prefix $YOUR_QT_PATH make sudo make install 其中,$YOUR_QT_PATH为你想要安装Qt的目录。 步骤五:测试 在终端中输入以下命令: $YOUR_QT_PATH/bin/qmake make 编译完成后,在终端中输入: ./your_app_name 即可启动你的Qt应用程序。 以上就是Qt5.9.8保姆安装教程了,希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值