Trong phần này chúng ta sẽ học cách gửi các yêu cầu HTTP và nhận file HTML gửi về bằng lớp QNetworkAccessManager.
QNetworkAccessManager
Lớp QNetworkAccessManager
cho phép ứng dụng gửi các yêu cầu và nhận trả lời qua mạng. Đối tượng QNetworkAccessManager
lưu trữ các phương thức kết nối mạng, cấu hình thường dùng và các thiết lập cần thiết cho các yêu cầu được gửi đi, thông số proxy và cache, các Signal liên quan… Lớp QNetworkAccessManager
rất mạnh, gần như bạn chỉ cần tạo một đối tượng QNetworkAccessManager
là có thể dùng cho toàn bộ ứng dụng Qt.
Khi bạn tạo một đối tượng QNetworkAccessManager
và dùng nó để gửi các yêu cầu qua mạng thì thông điệp gửi về sẽ nằm trong một đối tượng QNetworkReplpy
.
Mini Browser
Chúng ta sẽ dùng QNetworkAccessManager
để gửi yêu cầu HTTP và lấy về một file HTML.
minibrowser.pro
... QT += core QT += gui widgets QT += webkitwidgets QT += network ...
Đầu tiên bạn phải chỉ định một số module được dùng trong file .pro bao gồm network,
webkitwidgets
.
#include <QPushButton> #include <QGridLayout> #include <QLineEdit> #include <QLabel> #include <QWidget> #include <QTextBrowser> #include <QtWebKitWidgets/QWebView> #include <QVBoxLayout> #include <QHBoxLayout> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QObject> class MiniBrowser : public QWidget { Q_OBJECT public: MiniBrowser(QWidget *parent = 0); public slots: void goToPage(); void receiveFinishedSignal(QNetworkReply*); private: QPushButton *goBtn; QLabel *urlLbl; QLineEdit *line; QWebView *browser; QNetworkAccessManager *manager; };
Lớp MiniBrowser
sẽ là cửa sổ chính.
QWebView *browser;
Lớp QWebView
là một widget hỗ trợ hiển thị trang web HTML.
public slots: void goToPage(); void receiveFinishedSignal(QNetworkReply*);
Slot gotoPage()
xử lý sự kiện click button. Slot receiveFinishedSignal()
xử lý thông điệp trả về của QNetworkAccessManager
.
#include "minibrowser.h" MiniBrowser::MiniBrowser(QWidget *parent) : QWidget(parent) { manager = new QNetworkAccessManager(); goBtn = new QPushButton("Go", this); urlLbl = new QLabel("Url:", this); line = new QLineEdit(this); browser = new QWebView(this); QVBoxLayout *vbox = new QVBoxLayout(this); QHBoxLayout *hbox = new QHBoxLayout(this); hbox->addWidget(urlLbl); hbox->addWidget(line); hbox->addWidget(goBtn); vbox->addLayout(hbox); vbox->addWidget(browser); setLayout(vbox); QObject::connect(goBtn, SIGNAL(pressed()), this, SLOT(goToPage())); QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveFinishedSignal(QNetworkReply*))); } void MiniBrowser::goToPage() { QNetworkRequest request(QUrl(this->line->text())); manager->get(request); } void MiniBrowser::receiveFinishedSignal(QNetworkReply *reply) { if(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302) { QUrl url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); manager->get(QNetworkRequest(url)); } QByteArray array = reply->readAll(); QString str = QString::fromUtf8(array.data(), array.size()); this->browser->setHtml(str); }
Chúng ta sẽ tạo một giao diện của một browser đơn giản và cài đặt các slot xử lý.
manager = new QNetworkAccessManager();
Tạo một đối tượng QNetworkAccessManager.
QNetworkRequest request(QUrl(this->line->text())); manager->get(request);
Để tiến hành gửi các lệnh request qua mạng thì chúng ta dùng phương thức get()
, phương thức này nhận một đối tượng QNetworkRequest
, đây là lớp lưu trữ các thông tin cấu hình chuẩn cho các giao thức ứng dụng, hàm khởi tạo QNetworkRequest
nhận một đối tượng QUrl
, QUrl
chẳng qua chỉ là một lớp lưu trữ thông tin của một đường dẫn Url bình thường.
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveFinishedSignal(QNetworkReply*)));
Sau khi gọi phương thức get(), QNetworkAccessManager sẽ thực hiện việc gửi yêu cầu và chờ thông điệp trả lời và sẽ thông báo qua SIGNAL finished(QNetworkReply*)
với dữ liệu đi kèm là một đối tượng QNetworkReply
, chúng ta kết nối signal này với slot receiveFinishedSignal()
để nhận lấy dữ liệu truyền về trong QNetworkReply
.
if(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302) { QUrl url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); manager->get(QNetworkRequest(url)); }
Bạn có thể sẽ nhận được một mã lỗi 302 nếu vào đường dẫn google.com,
mã này chuyển hướng bạn đến một đường dẫn khác nên mình lấy đường dẫn mới và gửi một yêu cầu khác.
QByteArray array = reply->readAll(); QString str = QString::fromUtf8(array.data(), array.size()); this->browser->setHtml(str);
Bạn có thể lấy toàn bộ nội dung thông điệp qua phương thức QNetworkReply::readAll()
, trong trường hợp này đây là một đoạn code HTML,
phương thức này trả về một đối tượng QByteArray()
nên nếu bạn muốn đọc kiểu text thì phải chuyển nó qua QString
bằng phương thức QString::fromUtf8()
. Cuối cùng bạn đưa nội dung HTML vô webview bằng phương thức setHtml()
.
#include <QApplication> #include "minibrowser.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MiniBrowser browser; browser.resize(640, 480); browser.setWindowTitle("Mini Browser"); browser.show(); return a.exec(); }
Nội dung HTML trả về có thể sẽ không đầy đủ hoặc lỗi vì chúng ta không thiết lập một số thông số dành cho giao thức HTTP. Trong bài này mình chỉ hướng dẫn các thao tác cơ bản với lớp QNetworkAccessManager
.