C++ /Qt 基于http 请求json 数据解析并加载网络图片
一、创建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);
}