【C++ /Qt】C++ /Qt 基于http 请求json 数据解析并加载网络图片

C++ /Qt 基于http 请求json 数据解析并加载网络图片

Demo效果图

一、创建Qt项目

二、添加网络模块

1.在.pro文件添加 QT += network

2.在头文件中申明网络请求所需要的类库

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>

3.添加私有成员和槽函数

QNetworkAccessManager * NetAccessManager;
void onReplied(QNetworkReply *reply);	//判断网络连接是否成功,返回网络请求后的数据,都存储在reply中

4.构造函数中对NetAcessManger 进行空间申请, 关联槽函数

 NetAccessManager = new QNetworkAccessManager(this);

//在网络请求成功之后会自动调用onReplied函数,对返回的数据包解析
 connect(NetAccessManager,&QNetworkAccessManager::finished,
            this,&MainWindow::onReplied);

三、添加请求网络的请求函数

1.在protected:中添加成员函数

protected:
	void GetNetJson();

2.实现

void MainWindow::GetNetJson()
{
    QUrl url("https://v.api.aa1.cn/api/api-gqsh/index.php?wpon=json");
    //调用get方法 QNetworkRequest对目标api网址发出请求
    NetAccessManager->get(QNetworkRequest(url));
}

3.并在MainWindow构造函数中调用该请求函数

四、实现onReplied()函数

1.首先测试网络是否畅通,简单写个测试onReplied()

void MainWindow::onReplied(QNetworkReply *reply){
    qDebug()<<"onReplied successed";
  	//此时在reply 中是请求到的json数据
}

2.完整函数

void MainWindow::onReplied(QNetworkReply *reply){
    qDebug()<<"onReplied successed";	
    
	int satus_code = reply->attribute(
    QNetworkRequest::HttpStatusCodeAttribute).toInt();
    //qDebug() 用于测试和查看网络信息
    qDebug()<<"operation: "<<reply->operation();
    qDebug()<<"satus_code: "<<satus_code;
    qDebug()<<"url: "<<reply->url();
    qDebug()<<"raw header: "<<reply->rawHeaderList();
    //satus_code 为200 表示请求成功 常见状态码 404 403 等
    if(reply->error() != QNetworkReply::NoError 
       ||satus_code != 200 ){
        qDebug()<<reply->errorString().toLatin1().data();
        QMessageBox::warning(this,"QtNetImg",
                             "网络连接失败",QMessageBox::Ok);
    }else{
        QByteArray byteArray = reply->readAll();
        qDebug()<<"read all:" <<byteArray.data();
        //将获取到的所有信息通过readAll()传给fromNetJson
        //用于对数据解析
        //添加成员函数
        fromNetJson(byteArray);
    }
    reply->deleteLater();
}

五、添加解析json相关,并解析

1、添加响应库文件c++

#include <QCoreApplication>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>

2、添加成员函数

protected:
void fromNetJson(QByteArray &byteArr);

3、由于各种api接口返回的数据的类型不同,且字段和key-vlaue 都不同,所以每次的fromjsom 都大相不同,这里我是使用的免费API - 提供免费接口调用平台 ,其中的https://v.api.aa1.cn/api/api-gqsh/index.php?wpon=json接口,它的返回json很简单:

{
    "error":0,
    "result":200,
    "img":"//v.api.aa1.cn/api/api-gqsh/img/498.png"
}

我们只需要其中的"img"。所以我们需要先将传入的QByteArray类型数据转化成

QJsonDocument类型,以便于后续操作

QJsonDocument doc = QJsonDocument::fromJson(byteArr);

在转化为doc之后,我们将开始解析doc,因为json内容中只包含了三项,没有其他的Json对象或者Json数组,所以只用定义一个QJsonObjiect,

QJsonObject  Imgobj = doc.object();

我们再在定义一个成员变量 QString ImgUrl;用于存放解析出的url地址c++

//由于地址前没有加协议,所以这里直接添加http: 或者https:
ImgUrl = "https:" + obj.value("img").toString();

至此,将含有图片url的json解析完毕。

void MainWindow::fromNetJson(QByteArray &byteArr)
{

    QJsonDocument doc = QJsonDocument::fromJson(byteArr);
    if(!doc.isObject()){
        qDebug()<<"Netjson not an jsonObject!";
        return;
    }
    //2.开始解析
    QJsonObject obj = doc.object(); 
    ImgUrl = "http:" + obj.value("img").toString();
    qDebug()<<ImgUrl;
}

六、请求图片地址并解析图像数据,存放在QByteArray中

请求访问图片地址时,与上面请求获取图片的地址时基本一致

1.添加成员变量

private:
    //http
    QNetworkAccessManager * ImgNetAccessManager;
    QString ImgUrl;
    QPixmap *currentPicture;
    QByteArray ByteImg;	//存放图片二进制数据

2.添加成员函数

protected:
	//
	void onRepliedImg(QNetworkReply *replyImg);
	//请求Imgurl 并返回图片数据,传入获取到的图片资源,并调用
	void GetNetImgJson(QString url);
	//将获取到的图片传入ui->label->setPixmap(img)
	void fromJsonImg(QByteArray &JsonImg);

3.实现成员函数

首先时GetNetImgJson(),主要功能为:测试获取的图片网址是否可以联通,并将获取的图片资源通过调用onRepliedImg(QNetworkReply *replyImg);

所以要再在构造中进行connect 绑定槽,如果网络成功,将自动调用onRepliedImg();

connect(ImgNetAccessManager,&QNetworkAccessManager::finished,
            this,&MainWindow::onRepliedImg);

函数实现:


//这里我原本打算写GetNetJson()的重载的,但后来有bug,就舍弃了。😄
void MainWindow::GetNetImgJson(QString url)
{
    ImgNetAccessManager->get(QNetworkRequest(url));
}

将replyImg->readAll(); 存放在QByteArray ByteImg,的成员变量中,以便于后续需调用。


void MainWindow::onRepliedImg(QNetworkReply *replyImg)
{
    qDebug()<<"图片资源请求成功";
    int satus_code = replyImg->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"operation: "<<replyImg->operation();
    qDebug()<<"satus_code: "<<satus_code;
    qDebug()<<"url: "<<replyImg->url();
    qDebug()<<"raw header: "<<replyImg->rawHeaderList();
    if(replyImg->error() != QNetworkReply::NoError ||satus_code != 200 ){
        qDebug()<<replyImg->errorString().toLatin1().data();
        QMessageBox::warning(this,"QtNetImg","网络连接失败",QMessageBox::Ok);
    }else{
          ByteImg = replyImg->readAll();
        //这里调用fromJsonImg(),将获取到的数据传入进行解析,并显示
          fromJsonImg(ByteImg);
    }
    replyImg->deleteLater();
}

实现fromJsonImg(QByteArray &JsonImg),

void MainWindow::fromJsonImg(QByteArray &ByteImg)
{
    //定义QPixmap类 对象
    QPixmap Pixmap;
    //loadFromData方法,
    Pixmap.loadFromData(ByteImg);
    if (Pixmap.loadFromData(ByteImg)) {
	//加载成功,使用pixmap对象
    Pixmap.scaled(this->size(), Qt::KeepAspectRatio);	//设置图片大小为当前窗口大小,并保持横纵比
    ui->label_img->setScaledContents(true);		//设置可以缩放
    ui->label_img->setPixmap(Pixmap);
	} else {
	//加载失败
	qDebug()<<"图片资源加载失败,或者不支持当前图片格式";
    ui->label_img->setText("图片资源加载失败,或者不支持当前图片格式");
	}
}

补充:loadFromData

loadFromData QPixmap类的函数,它从'QByteArray 加载图像数据,并从中创建一个pixmap对象。它以一个QByteArray 对象作为参数,其中包某种格式的图像数据(例如PNG, JPEG, BMP)。

该函数返回一个布尔值,表示图像加载是否成功。

loadFromData 函数在我们没有直接访问图像文件,而是在字节数组中有它的数据时很有用。这可以用来加载从网络接收到的图像或动态生成的图像。

下面是如何使用loadFromData 的示例:

QByteArray imageData;//假设该数据包含JPEG格式的图像
QPixmap pixmap;
if (pixmap. loadFromData(imageData, "JPEG")) {
//加载成功,使用pixmap对象
/ /……
} else {
//加载失败
/ /……
}

在这个例子中, loadFromData函数是用imageData 中的图像数据和指定为 “JPEG” 的图像格式调用的。如果加载成功,我们就可以使用“pixmap”对象。如果加载失败,我们可以适当地处理错误。

七、设置button进行刷新,以获取下一张随机图片的地址,并显示到UI中

1.首先在ui中对添加相应的空间和布局,主要控件就两个,一个label用来显示图像,pushbutton刷新资源,布局可以自定义,如何美观如何来
添加控件

2.转到槽,右键单击button控件

转到槽

实现槽函数:在点击按钮时,我们需要访问含有图片网络路径的网址Api来获取json,解析出网址,并再次访问图片的网络路径,将其解析值成员变量中,并绘制到label上,因此只要调用以上的GetNetJson(),和 GetNetImgJson(ImgUrl),fromJsonImg(ByteImg);就可以在屏幕上显示。

源码敬上

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QCoreApplication>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QDebug>
#include <QFile>


#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:

    void onReplied(QNetworkReply *reply);

    void GetNetJson();
    void GetNetImgJson(QString url);

    void fromNetJson(QByteArray &byteArr);

    void onRepliedImg(QNetworkReply *replyImg);
    void fromJsonImg(QByteArray &JsonImg);

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    //http
    QNetworkAccessManager * NetAccessManager;
    QNetworkAccessManager * ImgNetAccessManager;

    QString ImgUrl =  QString("http://v.api.aa1.cn/api/api-gqsh/img/259.jpg");

    QPixmap *currentPicture;

    QByteArray ByteImg;

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    NetAccessManager = new QNetworkAccessManager(this);
    ImgNetAccessManager = new QNetworkAccessManager(this);

    connect(NetAccessManager,&QNetworkAccessManager::finished,
            this,&MainWindow::onReplied);

    connect(ImgNetAccessManager,&QNetworkAccessManager::finished,
            this,&MainWindow::onRepliedImg);


    GetNetJson();
    GetNetImgJson(ImgUrl);
   // setWindowFlag(Qt::FramelessWindowHint); //设置无边框
    setFixedSize(width(),height());     //设置固定当前窗口大小
}

MainWindow::~MainWindow()
{
    delete ui;
}
//http 网络请求
void MainWindow::GetNetJson()
{
    QUrl url("https://v.api.aa1.cn/api/api-gqsh/index.php?wpon=json");
    NetAccessManager->get(QNetworkRequest(url));
}


void MainWindow::GetNetImgJson(QString url)
{
    ImgNetAccessManager->get(QNetworkRequest(url));
}

//获取json数据,其中包含图片url readall 存在byteArr中
//最后调用fromjson 解析出qstring imgurl
void MainWindow::onReplied(QNetworkReply *reply)
{

    qDebug()<<"网络请求成功";
    int satus_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"operation: "<<reply->operation();
    qDebug()<<"satus_code: "<<satus_code;
    qDebug()<<"url: "<<reply->url();
    qDebug()<<"raw header: "<<reply->rawHeaderList();
    if(reply->error() != QNetworkReply::NoError ||satus_code != 200 ){
        qDebug()<<reply->errorString().toLatin1().data();
        QMessageBox::warning(this,"QtNetImage","网络连接失败",QMessageBox::Ok);
    }else{
        QByteArray byteArray = reply->readAll();
        qDebug()<<"read all:" <<byteArray.data();

        //QPixmap Pixmap;
        //Pixmap.loadFromData(byteArray);
        fromNetJson(byteArray);
    }
    reply->deleteLater();
}

/*
{
    "error":0,
    "result":200,
    "img":"//v.api.aa1.cn/api/api-gqsh/img/305.jpg"
}
*/
//将imgurl 存储成员变量中
void MainWindow::fromNetJson(QByteArray &byteArr)
{
    QJsonDocument doc = QJsonDocument::fromJson(byteArr);
    if(!doc.isObject()){
        qDebug()<<"Netjson not an jsonObject!";
        return;
    }
    //2.开始解析
    QJsonObject obj = doc.object();
    ImgUrl = "http:" + obj.value("img").toString();
    qDebug()<<ImgUrl;
}

void MainWindow::onRepliedImg(QNetworkReply *replyImg)
{
    qDebug()<<"图片资源请求成功";
    int satus_code = replyImg->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"operation: "<<replyImg->operation();
    qDebug()<<"satus_code: "<<satus_code;
    qDebug()<<"url: "<<replyImg->url();
    qDebug()<<"raw header: "<<replyImg->rawHeaderList();
    if(replyImg->error() != QNetworkReply::NoError ||satus_code != 200 ){
        qDebug()<<replyImg->errorString().toLatin1().data();
        QMessageBox::warning(this,"QtWeather","网络连接失败",QMessageBox::Ok);
    }else{
        //QByteArray byteArray = replyImg->readAll();
        //qDebug()<<"read all:" <<byteArray.data();

//        QPixmap Pixmap;
//        Pixmap.loadFromData(byteArray);
          ByteImg = replyImg->readAll();
            //QString data = QString::fromStdString(ImageData.toStdString());
          //  QPixmap Pixmap;
          //  Pixmap.loadFromData(ImageData);
       //  ui->label_img->setPixmap(Pixmap);
        fromJsonImg(ByteImg);
    }
    replyImg->deleteLater();
}

void MainWindow::fromJsonImg(QByteArray &ByteImg)
{
    //定义QPixmap类 对象
    QPixmap Pixmap;
    //loadFromData方法,
    Pixmap.loadFromData(ByteImg);
    if (Pixmap.loadFromData(ByteImg)) {
	//加载成功,使用pixmap对象
    Pixmap.scaled(this->size(), Qt::KeepAspectRatio);	//设置图片大小为当前窗口大小,并保持横纵比
    ui->label_img->setScaledContents(true);		//设置可以缩放
    ui->label_img->setPixmap(Pixmap);
	} else {
	//加载失败
	qDebug()<<"图片资源加载失败,或者不支持当前图片格式";
    ui->label_img->setText("图片资源加载失败,或者不支持当前图片格式");
	}
}

void MainWindow::on_pushButton_clicked()
{
     fromJsonImg(ByteImg);
     GetNetJson();
     GetNetImgJson(ImgUrl);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值