Qt 网络请求

在 Qt 中,发送网络请求可以有多种方式,例如使用 QTcpSocket 类,QHttp 类,QNetworkAccessManager 类等。我们在这里使用 QNetworkAccessManager 类来发送网络请求。

网络请求流程

  1. 创建 QNetworkAccessManager 对象。
  2. 创建 QNetworkRequest 对象,设置请求的 URL
  3. 使用 QNetworkAccessManager 对象发起网络请求,并设置相应的回调函数
  4. 等待网络请求完成。
  5. 处理网络请求的结果。

QUrl 类

QUrl 是 Qt 框架中用于处理和解析统一资源定位符(URL)的类。它可以表示一个 URL,并提供了一系列的方法来访问和修改 URL 的各个组成部分,比如协议(scheme)、主机名(host)、端口号(port)、路径(path)、查询字符串(query)和片段(fragment)等。

主要功能

  • 解析 URL:将字符串解析为 URL 的各个组成部分。
  • 构建 URL:从各个组成部分构建一个完整的 URL。
  • 访问和修改 URL 组件:提供方法访问和修改 URL 的各个部分。
  • 编码和解码:对 URL 进行编码和解码,确保 URL 符合规范。

常用方法

  • 构造函数

    • QUrl():创建一个空的 URL。
    • QUrl(const QString &url, QUrl::ParsingMode mode = QUrl::TolerantMode):从字符串创建一个 URL。
    • QUrl(const QUrl &other):从另一个 QUrl 对象创建一个 URL。
  • 访问 URL 组件

    • scheme():返回 URL 的协议部分。
    • host():返回 URL 的主机名部分。
    • port(int defaultPort = -1):返回 URL 的端口号部分。
    • path():返回 URL 的路径部分。
    • query():返回 URL 的查询字符串部分。
    • fragment():返回 URL 的片段部分。
  • 修改 URL 组件

    • setScheme(const QString &scheme):设置 URL 的协议部分。
    • setHost(const QString &host):设置 URL 的主机名部分。
    • setPort(int port):设置 URL 的端口号部分。
    • setPath(const QString &path):设置 URL 的路径部分。
    • setQuery(const QString &query):设置 URL 的查询字符串部分。
    • setFragment(const QString &fragment):设置 URL 的片段部分。
  • 编码和解码

    • toEncoded(QUrl::FormattingOptions options = QUrl::FullyEncoded):将 URL 编码为字节序列。
    • fromEncoded(const QByteArray &encodedUrl, QUrl::ParsingMode mode = QUrl::TolerantMode):从编码的字节序列创建一个 URL。
  • 其他方法

    • isValid():检查 URL 是否有效。
    • isEmpty():检查 URL 是否为空。
    • isLocalFile():检查 URL 是否表示本地文件。
    • toLocalFile():将 URL 转换为本地文件路径。

QNetworkAccessManager 类

QNetworkAccessManager 类是 Qt 框架中用于管理网络请求的类。它负责发送网络请求,接收网络响应,并管理网络连接。

主要功能

  • 发送网络请求:使用 QNetworkAccessManager 对象发起网络请求,并设置相应的回调函数。
  • 接收网络响应:当网络请求完成时,QNetworkAccessManager 对象会调用相应的回调函数,并将网络响应传递给回调函数。
  • 管理网络连接QNetworkAccessManager 对象会自动管理网络连接,包括创建连接、发送数据、接收数据、关闭连接等。

常用方法

  • 构造函数

    • QNetworkAccessManager():创建一个空的 QNetworkAccessManager 对象。
  • 发送网络请求

    • QNetworkReply *get(const QNetworkRequest &request):发送一个 HTTP GET 请求。
    • QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data):发送一个 HTTP POST 请求。
    • QNetworkReply *head(const QNetworkRequest &request):发送一个 HTTP HEAD 请求。
    • QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data):发送一个 HTTP PUT 请求。
    • QNetworkReply *deleteResource(const QNetworkRequest &request):发送一个 HTTP DELETE 请求。
    • QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, const QByteArray &data):发送一个自定义请求。
  • 设置回调函数

    • void setOperation(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QNetworkAccessManager::OperationCallback callback = 0):设置网络请求的操作类型和请求信息,并设置相应的回调函数。
    • void finished(QNetworkReply *reply):当网络请求完成时,调用此回调函数。
    • void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessibility):当网络连接状态改变时,调用此回调函数。
  • 其他方法

    • QNetworkConfigurationManager *configurationManager():返回 QNetworkConfigurationManager 对象,用于管理网络配置。
    • QNetworkCookieJar *cookieJar():返回 QNetworkCookieJar 对象,用于管理网络 cookie。
    • QNetworkDiskCache *cache():返回 QNetworkDiskCache 对象,用于管理网络缓存。
    • QNetworkReply *createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request):创建一个网络请求。
    • void setCache(QNetworkDiskCache *cache):设置 QNetworkDiskCache 对象,用于管理网络缓存。
    • void setCookieJar(QNetworkCookieJar *cookieJar):设置 QNetworkCookieJar 对象,用于管理网络 cookie。

QtWebEngine 引擎

在 Qt 中,有几种方法可以渲染浏览器界面,主要取决于你使用的 Qt 版本和具体需求。以下是一些常见的方法:

1. 使用 QWebEngineView(推荐)

QWebEngineView 是基于 Chromium 浏览器引擎的控件,适用于 Qt 5.4 及以后的版本。它提供了强大的网页渲染能力,支持 HTML5、CSS3 和 JavaScript。

首先使用MSVC2019创建项目,然后在.pro文件中添加 QT += webenginewidgets

示例代码

#include <QApplication>
#include <QWebEngineView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWebEngineView view;
    view.load(QUrl("https://www.example.com"));
    view.show();

    return app.exec();
}

2. 使用 QWebView(已废弃)

QWebView 是基于 WebKit 的控件,适用于 Qt 5.0 到 5.4 的版本。从 Qt 5.6 开始,QWebView 被废弃,推荐使用 QWebEngineView

示例代码

#include <QApplication>
#include <QWebView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWebView view;
    view.load(QUrl("https://www.example.com"));
    view.show();

    return app.exec();
}

3. 使用 QAxWidget(仅限 Windows)

如果你使用的是 Qt 5.6 以后的 mingw 版本,由于 QWebEngine 不支持 mingw,可以使用 QAxWidget 控件来嵌入 IE 浏览器。

示例代码

#include <QApplication>
#include <QAxWidget>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QAxWidget *axWidget = new QAxWidget("Shell.Explorer");
    axWidget->dynamicCall("Navigate2(const QString&)", "https://www.example.com");
    axWidget->resize(800, 600);
    axWidget->show();

    return app.exec();
}

4. 使用 QtWebEngine 模块

QtWebEngine 模块提供了 C++ 类和 QML 类型,用于呈现 HTML、XHTML 和 SVG 文档,支持 CSS 和 JavaScript。

示例代码

#include <QApplication>
#include <QWebEngineView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWebEngineView *view = new QWebEngineView;
    view->load(QUrl("https://www.example.com"));
    view->show();

    return app.exec();
}

5. 使用 QUltralight(轻量级替代品)

QUltralightQt WebEngineQt WebKit 的一个轻量级替代品,提供了一个可嵌入到应用程序中的 Web 界面。

示例代码

#include <QApplication>
#include <QUltralightView>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QUltralightView view;
    view.load(QUrl("https://www.example.com"));
    view.show();

    return app.exec();
}

总结

  • **推荐使用 QWebEngineView**:适用于大多数现代 Qt 应用程序,支持最新的 Web 技术。
  • **使用 QWebView**:仅适用于旧版本的 Qt(5.0-5.4)。
  • **使用 QAxWidget**:仅限 Windows 平台,适用于不支持 QWebEngine 的 mingw 版本。
  • **使用 QUltralight**:轻量级替代品,适用于需要更小体积的应用程序。

代码

QNetworkAccessManager 的使用

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

    networkacessmanager = new QNetworkAccessManager(this);
    ui->textBrowser->setStyleSheet("border : 2px solid blue");
    ui->textBrowser->setText("请在下方输入你的url地址");

    connect(networkacessmanager, &QNetworkAccessManager::finished,[this]( QNetworkReply *reply){
        if (reply->error() == QNetworkReply::NoError)
        {
            QByteArray data = reply->readAll();
            qDebug() << "Page content:" << data;
            ui->textBrowser->append(QString::fromUtf8(data));
            cout << "append";
        }
        else
        {
            qDebug() << "Error:" << reply->errorString();
        }
        reply->deleteLater();
    });
}


/* ...... */
void Widget::on_pushButton_clicked()
{
    QString urlstr = ui->lineEdit->text().trimmed();
    cout << urlstr ;
    QUrl url(urlstr);
    if(url.isValid()){
        networkacessmanager->get(QNetworkRequest(url)); // 向url发送请求
    }

}

QWebEngineWidget 使用

#include "widget.h"

#include <QApplication>
#include <QWebEngineView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.load(QUrl("https://baidu.com"));
    w.show();
    return a.exec();
}