向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI
Posted
技术标签:
【中文标题】向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI【英文标题】:Make get request to web service, get json response and update GUI in Qt 【发布时间】:2016-09-15 19:18:01 【问题描述】:尝试使用 Qt(使用 Qt Creator 4.1.0)学习 Web 服务并将数据连接到 GUI。我已经阅读了几个在线示例(最值得注意的是:1、2 和 3),但我的编码水平较低,而且我找不到能证明我的需求的完整示例,这导致我来到这里 :)。
我创建了一个简单的例子来包含我所有的缺点:
每 30 秒向(现有)网络服务发出 HTTP 获取请求。 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 中制作) 显示所有获取的解析数据:
我非常感谢任何完整的代码示例,这些示例展示了我们如何向 Web 服务发出请求,然后如何获取 json 响应。最后,如何在 Qt 中连接 GUI 以在收到数据后立即显示。
我刚开始研究这个领域,我需要一个简单的完整代码示例来帮助我学习。
【问题讨论】:
您是否编写了代码来每 30 秒向(现有)Web 服务发出 HTTP 获取请求?您显示了 JSON 格式和 GUI,但没有显示您尝试过的任何代码。 @Mike 我找到了QNetworkAccessManager
的一些示例,但是我的入门级缺少任何完整的教程和示例导致一无所获。所以,我没有实际的代码,只有几次失败的代码块尝试。上述问题的任何指南和代码都将帮助我深入研究该主题。
【参考方案1】:
这是一个完整的示例,说明如何使用 QNetworkAccessManager
将带有参数的 GET 请求发送到 Web 服务,并使用 QJsonDocument
解析 JSON 响应。
在示例中,我正在向http://uinames.com/
发送一个请求,其响应以 JSON 格式编码,格式如下:
"name":"John",
"surname":"Doe",
"gender":"male",
"region":"United States"
我正在解析 JSON 响应并将其显示在 GUI 中。
#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
如 cmets 中所述,如果您在窗口类的构造函数中使用它,则必须确保 networkManager
、networkRequest
、GUI 组件和此处的 timer
保持活动状态,只要您的窗口对象正在运行。因此,您可以选择将它们分配在堆中或作为类成员。
【讨论】:
这很完美,即使不是我的例子,它也清楚地表明了我想要理解的内容。谢谢。小问题,如果我有一个QMainWindow
类,这是否意味着你的所有代码都进入了该类的构造函数?
在与QMainWindow
的第一个问题相同的主题上,我尝试在课堂上复制您的代码(经过一些修改),但出现很多错误;也许您会简要解释一下它应该如何工作?谢谢
@nk-fford ,我无法访问您的网络服务,这就是为什么我按照您的要求编写了一个通用示例,该示例确实可以正常工作。不,您不会将所有代码原样复制到QMainWindow
的构造函数中。主要问题是networkManager
、networkRequest
和所有 GUI 组件都需要保持活动状态,只要您的 QMainWindow
正在运行。您可以选择将它们分配在堆上或作为类成员。此外,您可能希望将 lambda 函数替换为插槽。
如果您使用 GUI 设计器,默认情况下 GUI 组件是动态分配的,您可以使用 ui
指针访问它们。此处的示例演示了QNetworkAccessManager
和QJsonDocument
的用法。将其放入 QMainWindow
时遇到的问题属于通用 C++ 语言。我在 main
函数中编写所有代码的原因是为了让示例尽可能地最小化和可验证。
@nk-fford ,我已经更新了答案。尽管我认为这应该作为separate question 询问QTimer
,因为这与使用QNetworkAccessManager
和从Qt 访问Web 服务没有密切关系。以上是关于向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI的主要内容,如果未能解决你的问题,请参考以下文章