從 Qt WebKit 移植到 Qt WebEngine

以下章節包含移植應用程序的有關信息,使用 Qt WebKit QWebView API 要使用 Qt WebEngine QWebEngineView .

體係結構

Chromium provides its own network and painting engines, which Qt WebEngine uses. This, among other things, allows Qt WebEngine to provide better and more reliable support for the latest HTML5 specification than Qt WebKit. However, Qt WebEngine is thus also heavier than Qt WebKit and does not provide direct access to the network stack and the HTML document through C++ APIs.

類名

The Qt WebEngine equivalent of Qt WebKit C++ classes are prefixed by " QWebEngine" instead of " QWeb" .

Qt WebKit

#include <QWebHistory>
#include <QWebHistoryItem>
#include <QWebPage>
#include <QWebView>
QWebHistory
QWebHistoryItem
QWebPage
QWebView
					

Qt WebEngine

#include <QWebEngineHistory>
#include <QWebEngineHistoryItem>
#include <QWebEnginePage>
#include <QWebEngineView>
QWebEngineHistory
QWebEngineHistoryItem
QWebEnginePage
QWebEngineView
					
					

Qt 模塊名稱

在 qmake 工程文件中

Qt WebKit

QT += webkitwidgets
					

Qt WebEngine

QT += webenginewidgets
					
					

包括源文件模塊

Qt WebKit

#include <QtWebKit/QtWebKit>
#include <QtWebKitWidgets/QtWebKitWidgets> // With Qt >= 4.8
					

Qt WebEngine

#include <QtWebEngineWidgets/QtWebEngineWidgets>
					
					

QWebFrame 已閤並進 QWebEnginePage

HTML 框架可以把網頁劃分成幾個區域,在其中可以分彆錶示內容。

在 Qt WebKit,QWebFrame 錶示網頁內框架。每個 QWebPage 對象包含至少一框架,使用 QWebPage::mainFrame() 獲得主框架。創建額外框架采用 HTML <frame> 元素,其定義單個框架的外觀和內容,或采用 <iframe> 元素,在文本塊中插入框架。

在 Qt WebEngine,框架處理已被閤並進 QWebEnginePage 類。現在,所有子級框架被認為是內容的一部分,且隻可透過 JavaScript 進行訪問。QWebFrame 類的方法,如 load() 現在可直接透過 QWebEnginePage 本身。

Qt WebKit

QWebPage page;
connect(page.mainFrame(), SIGNAL(urlChanged(const QUrl&)), SLOT(mySlotName()));
page.mainFrame()->load(url);
					

Qt WebEngine

QWebEnginePage page;
connect(&page, SIGNAL(urlChanged(const QUrl&)), SLOT(mySlotName()));
page.load(url);
					
					

某些方法現在異步返迴結果

Because Qt WebEngine uses a multi-process architecture, calls to some methods from applications will return immediately, while the results should be received asynchronously via a callback mechanism. A function pointer, a functor, or a lambda expression must be provided to handle the results when they become available.

Qt WebKit

QWebPage *page = new QWebPage;
QTextEdit *textEdit = new QTextEdit;
// *textEdit is modified immediately.
textEdit->setPlainText(page->toHtml());
textEdit->setPlainText(page->toPlainText());
					

Qt WebEngine (采用 Lambda 函數在 C++11)

QWebEnginePage *page = new QWebEnginePage;
QTextEdit *textEdit = new QTextEdit;
// *textEdit must remain valid until the lambda function is called.
page->toHtml([textEdit](const QString &result){ textEdit->setPlainText(result); });
page->toPlainText([textEdit](const QString &result){ textEdit->setPlainText(result); });
					

Qt WebEngine (with a functor template wrapping a member function)

template<typename Arg, typename R, typename C>
struct InvokeWrapper {
    R *receiver;
    void (C::*memberFun)(Arg);
    void operator()(Arg result) {
        (receiver->*memberFun)(result);
    }
};
template<typename Arg, typename R, typename C>
InvokeWrapper<Arg, R, C> invoke(R *receiver, void (C::*memberFun)(Arg))
{
    InvokeWrapper<Arg, R, C> wrapper = {receiver, memberFun};
    return wrapper;
}
QWebEnginePage *page = new QWebEnginePage;
QTextEdit *textEdit = new QTextEdit;
// *textEdit must remain valid until the functor is called.
page->toHtml(invoke(textEdit, &QTextEdit::setPlainText));
page->toPlainText(invoke(textEdit, &QTextEdit::setPlainText));
					

Qt WebEngine (with a regular functor)

struct SetPlainTextFunctor {
    QTextEdit *textEdit;
    SetPlainTextFunctor(QTextEdit *textEdit) : textEdit(textEdit) { }
    void operator()(const QString &result) {
        textEdit->setPlainText(result);
    }
};
QWebEnginePage *page = new QWebEnginePage;
QTextEdit *textEdit = new QTextEdit;
// *textEdit must remain valid until the functor is called.
page->toHtml(SetPlainTextFunctor(textEdit));
page->toPlainText(SetPlainTextFunctor(textEdit));
					
					

Qt WebEngine 不與 QNetworkAccessManager 交互

某些 Qt Network 類,譬如 QAuthenticator were reused for their interface but, unlike Qt WebKit, Qt WebEngine has its own HTTP implementation and cannot go through a QNetworkAccessManager .

The signals and methods of QNetworkAccessManager that are still supported were moved to the QWebEnginePage 類。

Qt WebKit

QNetworkAccessManager qnam;
QWebPage page;
page.setNetworkAccessManager(&qnam);
connect(&qnam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticate(QNetworkReply*,QAuthenticator*)));
					

Qt WebEngine

QWebEnginePage page;
connect(&page, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticate(QNetworkReply*,QAuthenticator*)));
					

注意: 在 Qt WebEngine, QAuthenticator 必須被明確設為 null 以取消身份驗證:

*authenticator = QAuthenticator();
					

省略 QNetworkAccessManager 還影響證書管理辦法。更多信息,見 管理證書 .

關於個彆方法的注意事項

evaluateJavaScript

QWebFrame::evaluateJavaScript 被移動並重命名為 QWebEnginePage::runJavaScript 。目前,隻能在頁麵主框架運行 JavaScript,且結果會被異步返迴給所提供的 Functor (函子)。

Qt WebKit

QWebPage *page = new QWebPage;
qDebug() << page->mainFrame()->evaluateJavaScript("'Java' + 'Script'");
					

Qt WebEngine (采用 Lambda 錶達式在 C++ 11)

QWebEnginePage *page = new QWebEnginePage;
page->runJavaScript("'Java' + 'Script'", [](const QVariant &result){ qDebug() << result; });
					
					

setHtml 和 setContent

QWebEnginePage::setHtml and QWebEnginePage::setContent 異步履行方式如同正常 HTTP 加載,不像其 QWebPage 搭檔。

setContentEditable

QWebPage::setContentEditable 沒有等效的,因為透過最新 HTML 標準中的 contentEditable 屬性可以編輯任何文檔元素。 因此, QWebEnginePage::runJavaScript 就是所需要的。

Qt WebKit

QWebPage page;
page.setContentEditable(true);
					

Qt WebEngine

QWebEnginePage page;
page.runJavaScript("document.documentElement.contentEditable = true");
					
					

不可用 Qt WebKit API

此列錶中的 Qt WebKit 類和方法,將不可用於 Qt WebEngine。

QGraphicsWebView Qt WebEngine 被設計為使用硬件加速。因為不支持 Web View 類在 QGraphicsView ,除非將其附加到 QGLWidget 視口,否則此特徵超齣作用域。
QWebElement Qt WebEngine 使用多進程體係結構,這意味著對頁麵內部結構的訪問都必須異步完成,任何查詢結果都必須通過迴調被返迴。QWebElement API 是為同步訪問而設計的,因此,這需要徹底的重新設計。
QWebDatabase 在 Qt WebKit 中包裹的此 API Web SQL 數據庫特徵,已從 HTML5 標準中刪掉。
QWebPluginDatabase, QWebPluginFactory, QWebPluginInfo, QWebPage::setPalette, QWebView::setRenderHints Qt WebEngine 使用 Skia 渲染 Web 頁麵,不使用 QPainter 或 Qt 為此目的。HTML5 標準現在還提供瞭更好的替代,當 Qt WebKit 引入的本機控製插件不可用時。
QWebHistoryInterface 拜訪過的鏈接由 Qt WebEngine 自動持久化。
QWebPage::setContentEditable 在最新 HTML 標準中,編輯任何文檔元素可以通過 contentEditable 屬性。因此 runJavaScript 就是所需要的: page->runJavaScript("document.documentElement.contentEditable = true")
QWebPage::setLinkDelegationPolicy There is no way to connect a signal to run C++ code when a link is clicked. However, link clicks can be delegated to the Qt application instead of having the HTML handler engine process them by overloading the QWebEnginePage::acceptNavigationRequest () function. This is necessary when an HTML document is used as part of the user interface, and not to display external data, for example, when displaying a list of results.

注意: acceptNavigationRequest() starts the loading process and emits the loadStarted() signal before 請求被接受 (或拒絕)。因此, loadFinished() 信號返迴 false 是可預期的即使在委派請求後。