json - 向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI

标签 json qt web-services qt-creator qtnetwork

尝试使用 Qt(使用 Qt Creator 4.1.0)学习Web 服务将数据连接到 GUI。我已经阅读了几个在线示例(最著名的是:123),但是我的编码水平低,而且我找不到能够证明我的需求的完整示例,这让我来到了这里:)。

我创建了一个简单的示例,以便包含我所有的缺点:

  • 每 30 秒向(现有的)网络服务发出 HTTP get 请求
  • Web 服务然后通过发送一个 json 数据对象(参见下面的此类 json 示例格式)来响应,我们接收并解析
  • 然后,Qt 会将所有已解析的 json 数据显示到一个简单的 GUI 上(有关此类 GUI 的外观,请参见下文。

json 数据格式 - 示例:

{
    "city": "London",
    "time": "16:42",
    "unit_data": 
        [
            {
                "unit_data_id": "ABC123",
                "unit_data_number": "21"
            }
        ]
}

我的简单 Qt GUI 设计(在 Qt Creator 中制作) 显示所有获取的已解析数据: my simple Qt GUI design

如果有任何完整的代码示例展示了我们如何向 Web 服务发出请求以及如何获取 json 响应,我将不胜感激。最后,如何在 Qt 中连接 GUI 以在接收到这些数据后立即显示这些数据。

我刚刚开始研究这个领域,我需要一个简单的完整代码示例来帮助我继续学习。

最佳答案

这是一个完整的示例,说明如何使用 QNetworkAccessManager 将带有参数的 GET 请求发送到 Web 服务并使用 QJsonDocument 解析 JSON 响应.

在示例中,我向 http://uinames.com/ 发送了一个请求,其响应以 JSON 编码,格式如下:

{
    "name":"John",
    "surname":"Doe",
    "gender":"male",
    "region":"United States"
}

我正在解析 JSON 响应并将其显示在 GUI 中。

Example screenshot

#include <QtWidgets>
#include <QtNetwork>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //setup GUI (you could be doing this in the designer)
    QWidget widget;
    QFormLayout layout(&widget);
    QLineEdit lineEditName;
    QLineEdit lineEditGender;
    QLineEdit lineEditRegion;
    auto edits = {&lineEditName, &lineEditGender, &lineEditRegion};
    for(auto edit : edits) edit->setReadOnly(true);
    layout.addRow("Name:", &lineEditName);
    layout.addRow("Gender:", &lineEditGender);
    layout.addRow("Region:", &lineEditRegion);
    QPushButton button("Get Name");
    layout.addRow(&button);

    //send request to uinames API
    QNetworkAccessManager networkManager;
    QObject::connect(&networkManager, &QNetworkAccessManager::finished,
                     [&](QNetworkReply* reply){
        //this lambda is called when the reply is received
        //it can be a slot in your GUI window class
        //check for errors
        if(reply->error() != QNetworkReply::NoError){
            for(auto edit : edits) edit->setText("Error");
            networkManager.clearAccessCache();
        } else {
            //parse the reply JSON and display result in the UI
            QJsonObject jsonObject= QJsonDocument::fromJson(reply->readAll()).object();
            QString fullName= jsonObject["name"].toString();
            fullName.append(" ");
            fullName.append(jsonObject["surname"].toString());
            lineEditName.setText(fullName);
            lineEditGender.setText(jsonObject["gender"].toString());
            lineEditRegion.setText(jsonObject["region"].toString());
        }
        button.setEnabled(true);
        reply->deleteLater();
    });
    //url parameters
    QUrlQuery query;
    query.addQueryItem("amount", "1");
    query.addQueryItem("region", "United States");
    QUrl url("http://uinames.com/api/");
    url.setQuery(query);
    QNetworkRequest networkRequest(url);
    //send GET request when the button is clicked
    QObject::connect(&button, &QPushButton::clicked, [&](){
        networkManager.get(networkRequest);
        button.setEnabled(false);
        for(auto edit : edits) edit->setText("Loading. . .");
    });

    widget.show();
    return a.exec();
}

编辑:

自从您询问如何使用 QTimer要每隔一分钟触发一次更新,请将上面代码中按钮 clicked 信号的 connect 调用替换为如下代码:

QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&](){
    networkManager.get(networkRequest);
    button.setEnabled(false);
    for(auto edit : edits) edit->setText("Loading. . .");
});
timer.start(60000); //60000 msecs = 60 secs

如评论中所述,如果您在窗口类的构造函数中使用它,则必须确保 networkManagernetworkRequest、GUI 组件和只要您的窗口对象正在运行,这里的 timer 就会保持事件状态。因此,您可以选择将它们分配到堆中或作为类成员。

关于json - 向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39518749/

相关文章:

c++ - 在 Qt Stickman 示例中将火柴人的头像更改为我教授的头像

c# - 如何使用旧的 WSDL+XSD 和当前的 Web 服务位置在 C# 中进行 SOAP 调用?

java - 尝试使用 Jersey Client 下载文件时出现 HTTP 400 错误

json - 如何使用 PowerShell V2 使用 Websocket 客户端打开与 URL 的长期连接?

java - 从 Java Servlet for Datatables 将 JSON 数据作为字符串发送到 AJAX

java - 无法使用 son simple 解析 JSON 数组

web-services - 如何使用CXF将契约(Contract)优先的Web服务集成到Grails中?

javascript - 使用 d3 加载本地 JSON 文件

c++ - Controller 和 View 之间的耦合

windows - QSplashScreen 不使用与 QMainWindow 相同的默认监视器