向 Web 服务发出获取请求,获取 json 响应并在 Qt 中更新 GUI
Make get request to web service, get json response and update GUI in Qt
尝试使用 Qt(使用 Qt Creator 4.1.0)学习 Web 服务,并将数据连接到GUI。我已经阅读了几个在线示例(最著名的是:1, 2 and 3),但我的编码水平较低,而且我找不到能够证明我的需求的完整示例,这让我来到这里 :)。
我创建了一个简单的例子,包含了我所有的缺点:
- 每 30 秒向(现有)Web 服务发出 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 中制作) 显示所有获取的已解析数据:
如果有任何完整的代码示例展示了我们如何向 Web 服务发出请求以及如何获取 json 响应,我将不胜感激。最后,如何连接 Qt 中的 GUI 以在接收到这些数据后立即显示这些数据。
我刚刚开始研究这个领域,我需要一个简单的完整代码示例来帮助我前进。
这是一个完整的示例,说明如何使用 QNetworkAccessManager
and parse the JSON response using QJsonDocument
将带有参数的 GET 请求发送到 Web 服务。
在示例中,我向 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
如评论中所述,如果您在 window class 的构造函数中使用它,则必须确保 networkManager
、networkRequest
、只要您的 window 对象是 运行,GUI 组件和此处的 timer
就会保持活动状态。因此,您可以选择将它们分配到堆中或作为 class 成员。
尝试使用 Qt(使用 Qt Creator 4.1.0)学习 Web 服务,并将数据连接到GUI。我已经阅读了几个在线示例(最著名的是:1, 2 and 3),但我的编码水平较低,而且我找不到能够证明我的需求的完整示例,这让我来到这里 :)。
我创建了一个简单的例子,包含了我所有的缺点:
- 每 30 秒向(现有)Web 服务发出 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 中制作) 显示所有获取的已解析数据:
如果有任何完整的代码示例展示了我们如何向 Web 服务发出请求以及如何获取 json 响应,我将不胜感激。最后,如何连接 Qt 中的 GUI 以在接收到这些数据后立即显示这些数据。
我刚刚开始研究这个领域,我需要一个简单的完整代码示例来帮助我前进。
这是一个完整的示例,说明如何使用 QNetworkAccessManager
and parse the JSON response using QJsonDocument
将带有参数的 GET 请求发送到 Web 服务。
在示例中,我向 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
如评论中所述,如果您在 window class 的构造函数中使用它,则必须确保 networkManager
、networkRequest
、只要您的 window 对象是 运行,GUI 组件和此处的 timer
就会保持活动状态。因此,您可以选择将它们分配到堆中或作为 class 成员。