当前位置: 代码网 > it编程>编程语言>C/C++ > 保姆级教学QT实战项目:基于QT的音乐播放器(一)

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

2024年07月28日 C/C++ 我要评论
UI界面我就不细说了,可以自行参照设计,实现的功能有:1.搜索网络歌曲,但是这个网络歌曲是自己模拟的服务器,与各大音乐软件服务器或者API什么的无关2.歌词同步3.随机播放,上一首,下一首,暂停播放。主要就是这些按钮控件。最右边的按键就是歌曲列表与歌词页面的切换按钮最左边的为随机播放功能开启和关闭。


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


 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com