Займемся решением одной из самых простых, но и достаточно распространенных задач сетевого программирования: получения данных через GET-запрос. Для этого воспользуемся классом QNetworkAccessManager.
Замечание: Не забудьте, что для использования сетевых библиотек в Qt необходимо явно затребовать их в pro-файле проекта:
1 |
QT += network |
Создадим простое приложение, которое загружает данные по URL, и отображает их в текстовом поле:
Замечание 1: Компонент QTextEdit автоматически преобразовывает HTML-код в его читаемое представление, поэтому мы получаем очень ограниченную версию браузера (без работающих гиперссылок, css, изображений и JavaScript). Если же вам нужно полноценное отображение веб-страниц, то советую обратить внимание на QWebView.
Замечание 2: Наше приложение может загружать не только веб-страницы (и прочую текстовую информацию), но и бинарные данные (например, изображения) по их URL. Все упирается в визуализацию, которой сейчас нет.
И сразу к делу. Заголовочный файл networkmanagerdemowidget.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#ifndef NETWORKMANAGERDEMOWIDGET_H #define NETWORKMANAGERDEMOWIDGET_H #include <QWidget> #include <QNetworkAccessManager> namespace Ui { class NetworkManagerDemoWidget; } class NetworkManagerDemoWidget : public QWidget { Q_OBJECT public: explicit NetworkManagerDemoWidget( QWidget* parent = 0 ); ~NetworkManagerDemoWidget(); private slots: void onGo(); void onFinished( QNetworkReply* reply ); private: Ui::NetworkManagerDemoWidget* ui; QNetworkAccessManager m_manager; }; #endif // NETWORKMANAGERDEMOWIDGET_H |
Реализация networkmanagerdemowidget.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include "networkmanagerdemowidget.h" #include "ui_networkmanagerdemowidget.h" #include <QNetworkReply> NetworkManagerDemoWidget::NetworkManagerDemoWidget( QWidget* parent ) : QWidget( parent ), ui( new Ui::NetworkManagerDemoWidget ) { ui->setupUi( this ); connect( ui->bnGo, SIGNAL( clicked( bool ) ), SLOT( onGo() ) ); connect( &m_manager, SIGNAL( finished( QNetworkReply* ) ), SLOT( onFinished( QNetworkReply* ) ) ); } NetworkManagerDemoWidget::~NetworkManagerDemoWidget() { delete ui; } void NetworkManagerDemoWidget::onGo() { ui->lbStatus->setText( "Working..." ); QString urlText = ui->edUrl->text().trimmed(); m_manager.get( QNetworkRequest( QUrl( urlText ) ) ); } void NetworkManagerDemoWidget::onFinished( QNetworkReply* reply ) { if( reply->error() == QNetworkReply::NoError ) { QString data = QString::fromUtf8( reply->readAll() ); ui->textEdit->setText( data ); ui->lbStatus->setText( "Ready!" ); } else { ui->lbStatus->setText( reply->errorString() ); } // Мы сами должны освободить память для reply // Однако делать это через delete нельзя reply->deleteLater(); } |
Важно: Результат выполнения запроса приходит к нам асинхронно через сигнал finished() объекта m_manager. За освобождение ресурсов ответа reply ответственны мы, поэтому для предотвращения утечки памяти нужно вызвать reply->deleteLater().
Замечание: URL должен быть полным, поэтому без указания протокола (например http://) обработка запроса окончится неудачей.