用Qt实现基于网络请求的用户登录(二)

上一篇文章介绍了在Qt中与网络请求相关的类,以及在Qt中生成和解析Json。这一篇文章,将基于实例展示如何应用这些类实现网络请求,以及Json的生成和解析体现在哪里。
先回顾一下需要解决的问题:

  • 问题:用户联网登录

    1.提供登录界面(客户端),输入用户名和密码;
    2.将用户名和密码发送给服务器端,并进行相关查询,如果用户合法,返回用户信息;
    3.对返回的用户信息进行解析。

  • 假设:
    已经有了服务器和存储着用户名和密码数据库。服务器当接收到客服端的请求的时候,先在数据库中进行查询操作,然后返回用户信息。
    其中,客户端与服务器进行通信用到的接口信息如下所示:

【url】 /xxx1/xxx2/
【请求方式】 post
【请求参数说明】
{“username”:6到15个字符, 数字和字母的组合,非空,唯一
“passwd”:6到20个字符,非空}
【样例说明】
{“passwd”:”123456”,”username”:”haha”}
【返回信息】
{“code”:84,”message”:”登陆失败,验证码输入错误”}
{“code”:4,”message”:”账号异常”}
{“code”:5,”message”:”密码错误”}
{“code”:6,”message”:”用户名不存在”}

一、客户端界面
这里写图片描述

二、实现步骤
1.生成QNetworkRequest对象,设置请求头、请求所用API所需实参、url等信息;
在这里根据请求方式是post还是get,请求所用API所需实参的设置分两种情况:
①manager.post(request,data)
其中data为形如

"data={"username": "haha","passwd": 123456}"

这样的QByteArray。
②manager.get(request)
参数直接在设置request的URL的时候设置(post要另设置URL):

request.setUrl(QUrl("http://xxx1/xxx2?username="+username+"&passwd="+passwd));

2.准备解析处理QNetworkReply的slot;
3.生成QNetworkAccessManager,发送request,并将返回来的reply委托给该slot处理(实现上就是一条connect语句)

三、代码实现
1.在.pro中添加netwotk模块
因为与网络请求相关的那些类在这个模块里面

QT       += core gui   //原来存在的
QT       += network    //添加的

2.login.h文件

#ifndef LOGIN_H
#define LOGIN_H

#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>

namespace Ui {
class Login;
}

class Login : public QMainWindow
{
    Q_OBJECT

public:
    explicit Login(QWidget *parent = 0);
    ~Login();

private slots:
    void finishRequest(QNetworkReply*);  //处理reply的slot
    void on_OKButton_clicked();

private:
    Ui::Login *ui;
    QNetworkAccessManager manager;   //manager  相关注意点见后文
    QNetworkRequest request;    //request 
};

#endif // LOGIN_H

3.login.cpp

#include "login.h"
#include "ui_login.h"
#include <QMessageBox>
#include <QByteArray>
#include <QString>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonParseError>
#include <QJsonValue>
#include <QJsonObject>
#include <QDebug>
#include <iostream>

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

Login::~Login()
{
    delete ui;
}

void Login::on_OKButton_clicked()
{
    //获取用户名、密码
    QString username = ui->usrLineEdit->text();
    QString password = ui->pwdLineEdit->text();
    if(username.isEmpty() || password.isEmpty())
    {
        QMessageBox::warning(this,"Warning","Username or password is empty!",QMessageBox::Yes);
        ui->usrLineEdit->clear();
        ui->pwdLineEdit->clear();
    }
    else{
    //通过QJsonObject得到post需要的参数data, data形式为: "data={"username": "haha","passwd": 123456}"

    QJsonObject json;
    json.insert("username",username);
    json.insert("passwd",password);

    QJsonDocument document;
    document.setObject(json);

    QByteArray byte_array = document.toJson(QJsonDocument::Compact);
    QByteArray data;
    data.append("data="+byte_array);

    //设置request
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");  //上面语句固定这么写,要不然会报错“contest—type is missing”
    request.setRawHeader("XXX3", "XXX4");
    request.setUrl(QUrl("http://xxx1/xxx2/"));  //"http:"不要少

    //manager发送请求,并接收reply,委托给slot处理
    manager.post(request,data);
    connect(&manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishRequest(QNetworkReply*)));
  }
}

void Login::finishRequest(QNetworkReply *reply)
{
    if (reply->error()){
            qDebug()<<"Error!"<<endl;
    }else{
            //解析reply中携带的Json
            QByteArray byte_array = reply->readAll();  //Json ducument
            QJsonParseError json_error;
            QJsonDocument parse_document = QJsonDocument::fromJson(byte_array, &json_error);
            if(json_error.error == QJsonParseError::NoError)
            {
                  if(parse_document.isObject())
                  {
                      QJsonObject obj = parse_document.object();
                      if(obj.contains("code"))
                      {
                          QJsonValue code_value = obj.take("code");
                          int code_value_int = code_value.toInt();
                          if(code_value_int == 3)
                          {
                              QJsonValue message_value = obj.take("message");
                              qDebug()<<message_value<<endl;  //输出:QJsonValue(string, "登录成功")
                          }
                          else
                          {
                              QJsonValue message_value = obj.take("message");
                              qDebug()<< message_value<<endl;
                              QString error_message = message_value.toString();
                              QMessageBox::warning(this,"Error",error_message,QMessageBox::Yes);
                              ui->usrLineEdit->clear();
                              ui->pwdLineEdit->clear();

                          }
                    }
               }
           }
    }
     reply->deleteLater();
}

四、实现时遇到的问题

1.试图直接生成Json document
post(request,data)请求中所用到的data为形如

"data={"username": "haha","passwd": 123456}"

的Json document,由于是一QByteArray的形式保存的,所以就想着能不能直接生成这样的QByteArray,从而绕过QJsonObject、 QJsonDocument, 实验结果是不可以。

 //想通过QByteArray直接生成Json document,结果是不可以
    QByteArray data;
    data.append("username="+username);
    data.append("passwd="+password);

2.将manager 和 request设为了全局变量
在这个例子中,只有一次网络请求,因此看不出这样做有什么问题。但是,当程序中有好几个网络请求的时候,这些网络请求共用一套manager和request,就会出现问题了。因为connect语句,只要manager接收到reply,就会触发所有connect语句,所有的解析Json的slot都有可能被委托到。这样就会出现,为什么我发出网络请求的是第二部分,却会是第一部分的slot有所反应= =
如果一开始使用的是全局变量,简单地将用到全局变量manager 和 request的地方改为局部变量

    QNetworkAccessManager manager1;
    QNetworkRequest request1;

出现的结果是,根本就没有网络请求成功的迹象。应该使用指针:

    QNetworkAccessManager *manager1 = new QNetworkAccessManager();
    QNetworkRequest *request1= new QNetworkRequest();

原因参看:http://bbs.csdn.net/topics/391077810
但如果并不是由全局变量改为局部变量,采用第一种方式好像不会有什么问题。


参考资料:

网络请求基础相关:
Qt中网络请求相关类相关:
Qt实现网络数据传输: http://blog.sina.com.cn/s/blog_a6fb6cc90101fg0i.html
Post与get的区别: http://www.cnblogs.com/findumars/p/5574299.html
Qt网络编程之实例一GET方式: http://blog.csdn.net/chenlong12580/article/details/7392766
解决finished信号无法触发槽函数是看到的:
QNetworkAccessManager的finished信号无法触发槽函数: http://bbs.csdn.net/topics/391077810
QNetworkAccessManager : https://tieba.baidu.com/p/4089426961

Json相关:
Qt之JSON生成与解析: http://blog.sina.com.cn/s/blog_a6fb6cc90101gnxm.html
Json教程:http://www.w3school.com.cn/json/index.asp
http://www.w3school.com.cn/json/json_syntax.asp

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 基于Qt的电子网络白板的设计与实现主要包括界面设计、网络通信能力以及白板功能的实现。 首先是界面设计,使用Qt的图形界面设计工具创建白板的界面,包括画布、工具栏、菜单栏等。通过布局管理器来管理界面元素,使界面简洁美观,并考虑不同分辨率和平台的适配性。 其次是网络通信能力的实现,基于Qt网络模块,使用TCP/IP协议进行服务器和客户端之间的通信。服务器端负责接收客户端发来的数据,并将其广播给其他客户端,客户端则根据接收到的数据进行界面更新。通过网络通信,实现多用户在同一白板上进行协同编辑的功能。 最后是白板功能的实现,包括画线、画图形、撤销重做、文本编辑等。通过鼠标事件和键盘事件的处理,实现用户在白板上进行图形绘制和文本编辑的操作。同时,为了保证用户操作的同步性,需要对每个操作进行同步处理,确保操作在所有客户端上都可以看到。 综上所述,基于Qt的电子网络白板的设计与实现主要包括界面设计、网络通信能力以及白板功能的实现。通过合理的设计和实现,可以实现多用户协同编辑的功能,提高团队协作效率,使得用户可以方便地共享和编辑信息。 ### 回答2: 基于Qt的电子网络白板的设计与实现是基于Qt框架开发的一款多人协作的电子白板应用。该应用可以在网络环境下实现多人同时进行实时绘图、写字和标注等操作,实现远程团队协作。 在设计方面,首先需要借助Qt的图形库,实现画板的基本绘制功能。通过使用Qt提供的绘图类,如QPainter、QPen和QBrush等,可以实现各种绘制操作,包括线条、形状和文字等。 其次,需要设计用户间的通信机制。可以利用Qt网络编程模块,使用TCP或UDP协议与服务器进行通信。服务器负责接收和分发用户的操作请求,将其广播给其他在线用户。这样,每个用户都可以看到其他用户的操作,并实时更新本地画面。 在实现方面,首先需要设计用户界面,包括画板区域、工具栏和用户列表等。通过Qt的界面设计工具,可以方便地创建和布局这些界面元素,使用户能够直观地操作和使用电子白板。 接着,需要定义用户的操作事件和信号槽机制。用户可以通过点击工具栏的按钮选择绘画工具,也可以通过手写板或鼠标进行绘制。每个操作事件都会发送相应的信号,触发对应的槽函数,实现绘制效果。 最后,需要建立网络连接和通信的逻辑。每个用户首先连接到服务器,服务器会分配一个唯一的用户ID。用户之间通过服务器进行消息的传递和同步,保证多人协作的实时性和一致性。 综上所述,基于Qt的电子网络白板的设计与实现需要考虑绘制功能、用户界面设计、用户通信机制和操作事件与信号槽机制。通过合理的架构设计和代码实现,可以实现一个高效稳定、易用便捷的电子网络白板应用。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值