从Qt WebKit迁移到Qt WebEngine#

Qt WebKit和Qt WebEngine API差异概述。

以下各节包含有关将使用Qt WebKit QWebView API的应用程序迁移到使用Qt WebEngine QWebEngineView 的信息。

架构#

Chromium提供了自己的网络和绘制引擎,Qt WebEngine使用这些引擎。这使Qt WebEngine能够提供比Qt WebKit更好、更可靠的HTML5规范支持。然而,因此Qt WebEngine也相对比较重,并且不提供通过C++ API直接访问网络栈和HTML文档的能力。

类名称#

Qt WebEngine等效的是使用前缀“QWebEngine”而不是“QWeb”的Qt WebKit C++类。

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);

某些方法现在以异步方式返回其结果#

由于Qt WebEngine使用多进程架构,来自应用程序的一些方法调用将立即返回,而结果应该通过回调机制异步接收。必须在结果可用时提供函数指针、仿函数或lambda表达式来处理结果。

Qt WebKit

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

Qt WebEngine(使用C++11中的lambda函数)

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(使用封装成员函数的函数模板)

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(使用常规函数对象)

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,被重复使用其接口,但与Qt WebKit不同,Qt WebEngine有自己的HTTP实现,无法通过QNetworkAccessManager进行。

仍受支持的QNetworkAccessManager的信号和方法已移动到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已移动并更名为runJavaScript 。目前只能在对页面主框架运行JavaScript,并将结果异步返回给提供的函数对象。

Qt WebKit

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

Qt WebEngine(使用C++11中的lambda表达式)

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

setHtml和setContent#

setHtmlsetContent的异步执行方式与正常的HTTP加载相同,不同于它们的QWebPage对应物。

setContentEditable#

QWebPage::setContentEditable没有等效功能,因为任何文档元素都可以通过最新HTML标准中的contentEditable属性使其可编辑。因此,只需要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旨在与硬件加速一起使用。由于我们无法在不连接到QGLWidget视图端口的情况下在QGraphicsView中支持一个WebView类,因此此功能不在此范围内。

QWebElement

Qt WebEngine使用多进程架构,这意味着对页面内部结构的任何访问都必须异步完成,任何查询结果都必须通过回调返回。QWebElement API是为了同步访问而设计的,这需要进行完全的设计重设计。

QWebDatabase

此API在Qt WebKit中封装的Web SQL Database功能已从HTML5标准中删除。

QWebPluginDatabase、QWebPluginFactory、QWebPluginInfo、QWebPage::setPalette、QWebView::setRenderHints

Qt WebEngine使用Skia渲染网页,不使用QPainter或Qt实现这一功能。HTML5标准也提供了许多当Qt WebKit引入本地控件插件时不可用的更好的替代方案。

QWebHistoryInterface

Qt WebEngine会自动持久化已访问的链接。

QWebPage::setContentEditable

在最新的HTML标准中,任何文档元素都可以通过contentEditable属性设置为可编辑。因此只需要runJavaScript: page->runJavaScript("document.documentElement.contentEditable = true")

QWebPage::setLinkDelegationPolicy

没有方法可以将信号连接到点击链接时运行C++代码。然而,可以通过覆写acceptNavigationRequest()函数来将链接点击委托给Qt应用程序,而不是让HTML处理器引擎处理它们。这对于HTML文档作为用户界面的一部分使用时是必要的,而不是用于显示外部数据时,例如显示结果列表。

注意

acceptNavigationRequest()开始加载过程并发出loadStarted()信号请求被接受或拒绝之前。因此,即使在委托请求之后,也可以预期发出返回falseloadFinished()信号。