从Qt WebKit迁移到Qt WebEngine

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

架构

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

类名

Qt WebEngine与Qt WebKit C++类的对应关系前缀为"QWebEngine"而不是"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);

一些方法现在异步返回结果

因为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网络类,如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`已经移动并重命名为`QWebEnginePage::runJavaScript`。目前只能在页面的主框架上运行JavaScript,并且结果将异步返回到提供的functor。

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

QWebEnginePage::setHtmlQWebEnginePage::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中可用。

QGraphicsWebViewQt WebEngine旨在与硬件加速一起使用。因为我们无法在不将QGLWidget视口附加到之上时支持QGraphicsView的web视图类,因此该功能超出了范围。
QWebElementQt WebEngine使用多进程架构,这意味着对页面内部结构的任何访问都必须异步完成,任何查询结果都必须通过回调返回。QWebElement API是为同步访问设计的,这将需要一个完全的重设计。
QWebDatabase此API在Qt WebKit中封装的Web SQL Database功能已被HTML5标准删除。
QWebPluginDatabase, QWebPluginFactory, QWebPluginInfo, QWebPage::setPalette, QWebView::setRenderHintsQt WebEngine使用Skia渲染网页,并不使用QPainter或Qt来实现此目的。HTML5标准现在也提供了许多更好的备选方案,当在Qt WebKit中引入本地控件插件时,这些方案尚不可用。
QWebHistoryInterfaceQt WebEngine会自动保留已访问链接。
QWebPage::setContentEditable在最新的HTML标准中,任何文档元素都可以通过`contentEditable`属性进行编辑。所以只需要`runJavaScript`:`page->runJavaScript("document.documentElement.contentEditable = true")`。
QWebPage::setLinkDelegationPolicy当点击链接时,没有办法将信号连接以运行C++代码。然而,可以通过重载QWebEnginePage::acceptNavigationRequest() 函数,将链接点击委托给Qt应用程序处理,而不是由HTML处理引擎来处理这些点击事件。当使用HTML文档作为用户界面的一部分,并且不是为了显示外部数据时,例如显示结果列表时,这是必要的。

注意:acceptNavigationRequest() 在接受或拒绝请求之前开始加载过程并发射loadStarted() 信号。因此,即使委托了请求,也应预期返回 falseloadFinished() 信号。

© 2024 The Qt Company Ltd. 本文档中包含的贡献的文档版权属于其各自的拥有者。提供的文档是在Free Software Foundation发布的GNU自由文档许可版1.3的条款下许可的。Qt及其相关标志是The Qt Company Ltd.在芬兰和/或其他国家/地区的商标。所有其他商标均为其各自所有者的财产。