很遗憾,QtWebkits在Qt5.6以上版本被淘汰了,对于这个接口良且和其他类例如QWebFrame完美结合的组件就这么没了,我只能表示惋惜。对于QtWebEngine新的组件,不得不承认它从Chromium继承过来的强大的性能,但接口上还不是很丰富,和其他类的交互也不是很完美,期待Qt能够对其进行进一步开发,我也会不断的升级Qt,尝试新的接口。
目前而言,QWebEngine有以下缺点:
MinGW版本的Qt不支持,即便是Qt5.6版本以上也是不支持的。仅仅支持MSVC版本。
接口暂时不丰富
无法和QWebFrame进行交互(使用了新的QWebChannel和QWebEnginePage组合进行交互)
基于我们的GPS定位项目,参考:[Qt开发北斗定位系统融合百度地图API及Qt程序打包发布] ,我们在该项目中使用的是Qt5.5版本,在嵌入的浏览器作为加载地图用的是QWebKits组件,我们将其升级使用QWebEngine进行加载地图,和HTML和JS进行交互。我们以此为例,进行简要的介绍。
2. 两者的UI上面的区别
你刚刚升级到Qt5.6版本可能在UI设计界面时候在组件中找不到QWebEngineView这个组件,无法从这里拖拽这个组件到你的UI界面上。我查阅了很多资料,看到别人经常使用 ui->webEngineview->...这样,我甚至怀疑是否因为安装了其他版本的Qt影响到了我,我卸载了包含5.6版本的所有Qt,又重新安装了一遍,但是再重启软件后,依然没有发现QWebEngineView这个鬼东西。在Qt5.5中你也能发现有这样的组件QWebView,如图1所示:
QWebView组件可以通过QWebFrame来进行HTML和JS的通信,如果过渡到QWebEngineView,要是没有这个UI组件的话,我如何把浏览器嵌入到软件界面,实现网页和软件的混合编程呢。根据官方提供的一个例子中,cookiebrowser中找到了答案,这也是官方给的例子中,唯一一个嵌入到网页中的!(不得不说,Qt给的例子很模糊很差!) 经过研究, QWebEngineView使用widget组件,拖拉出来是一个透明的组件,对着组件按右键->promote to.. ->选择QWebEngineView,如图2,完成操作。
有了QWebEngineView这个UI组件,我们可以在程序中调用其成员、方法和函数完成操作了。
3. 使用方法区别
在使用方法上有很大的区别,可以说是两个完全不同理念的东西,这里为了更通俗易懂,就不粘贴API文档中函数解释,就用最常用的!
#include <QtWebEngineWidgets> // 基本组件#include <QWebEnginePage> // HTML页面#include <QWebChannel> // C++和JS/HTML双向通信,代替了已淘汰的QtWebFrame的功能在我们的项目中一开始就要引入这样的组件,但在我们的项目中,没有频繁用到与JS的互相交互,所以这里暂时没有关于QWebChannel的使用方法,只留下这个接口。
以下为区别:
在WebKits中的初始化:
QUrl url(strMapPath) // strMapPath为QString类,是你html文件的路径ui->webView->load(url)ui->webView->setContentsMargins(0,0,0,0)
ui->webView->setTextSizeMultiplier(1)//设置网页字体大小connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(slotPopulateJavaScriptWindowObject()))
我们会使用load方法加载html所在的界面,使用QWebFrame类的mainFrame()中的SIGNAL和槽函数
void Widget::slotPopulateJavaScriptWindowObject(){
ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("ReinforcePC", this)
}
进行响应。参考文献1:《javascript调用qt》,可以解释这个槽函数的重要性。
在WebEngine中的初始化:
QWebEnginePage *page = new QWebEnginePage(this) // 定义一个page作为页面管理QWebChannel *channel = new QWebChannel(this) // 定义一个channel作为和JS或HTML交互page->load(strMapPath) // page上加载html路径page->setWebChannel(channel) // 把channel配置到page上,让channel作为其信使ui->webEngine->setPage(page) // 建立page和UI上的webEngine的联系如果你的 初始化程序写到这里,当你运行程序的时候,无论是webKits里的WebView还是新版的webEngineView,你的UI界面上的那个组件区域就会显示那个html文件了。
到此,我们完成了两者的初始化。
WebKits组件中的运行JS:
我们以按钮的槽函数为例,当点击按钮时,会向JS发送命令,运行JS脚本,我们这里发送的是将显示变为卫星图的JS命令:
void Widget::on_pushButtonStreetMap_clicked(){ QWebFrame *frame = ui->webView->page()->mainFrame()// 定义一个QWebFrame负责交互
QString cmd = QString("showStreetMap()")// JS的命令
frame->evaluateJavaScript(cmd) // 使用frame下的命令运行该命令}
从这个例子中我们也可以看到,QWebFrame是JS交互的关键。
WebEngine组件中的运行JS:
还是以该槽函数为例:
void Widget::on_pushButtonSatelliteMap_clicked(){ QString cmd = "showSatelliteMap()"
ui->webEngine->page()->runJavaScript(cmd) // 直接page()下就可以运行}
在JS单向通信中十分简单,也不需要使用QWebChannel信使,但该方法runJavaScript()无法在构造函数中使用,原因不明。也可以这样使用:
connect(ui->webEngine,&QWebEngineView::loadFinished,[=](int){ui->webEngine->page()->runJavaScript(cmd1)
第二个参数SIGNAL位置的,只能使用这样的方式调用,如果使用SIGNAL(....loadFinished),报错。
WebKit 是一个开源的浏览器引擎,与之相应的引擎有Gecko(Mozilla Firefox 等使用的排版引擎)和Trident(也称为MSHTML,IE使用的排版引擎)。同时WebKit 也是苹果Mac OS X 系统引擎框架版本的名称,主要用于Safari,Dashboard,Mail 和其他一些Mac OS
X 程序。WebKit 所包含的 WebCore 排版引擎和 JSCore 引擎来自于 KDE 的 KHTML 和 KJS,当年苹果比较了 Gecko 和
KHTML 后,仍然选择了后者,就因为它拥有清晰的源码结构、极快的渲染速度。
鉴于最近项目中需要用到原生与JS交互,以前做过交互,但是没有总结一个demo,这次做的时候都忘记了,所以这次做了一个swift 和 OC 的demo。方便以后需要用交互功能的时候查看。
由于也没有难的点,所以这里就不做技术上的讲解了。直接上的地址: iOS webKit (swift + oc) 原生交互Demo . demo里包含了Swift 版和 OC版 ,由于UIWebView的性能相比webkit而言,相差甚远,在加上现在的项目基本都支持8.0以上的系统,所以基本可以放弃UIWebview了。