目录
引言
最近需要升级Qt版本,而Qt5.6之后QWebKit已经被废弃,转而使用基于chromium内核、性能更好、问题更少的QWebEngine。
引入前需要在pro中新增对应模块,如果之前没有安装过该模块需要通过MaintenanceTool安装
QT += webenginewidgets
QWebEngine与QWebKit主要差异
1.交互方式修改
QWebEngine与QWebKit最大差异就是与web段交互方式修改,由同步改为异步,之前runJs可以同步获得返回值,现在需要从回调函数中获取。
Js的调用函数也由page()->mainFrame()->evaluateJavaScript(jsStr)替换为page()->runJavaScript(jsStr);
2.Html5兼容性
QWebEngine对Html5的兼容性更好,诸如在对3D地图Cesium的支持上,性能显著优于QWebKit
3.参数设置类修改
QWebSettings替换为QWebEngineSettings,原有的部分参数也被废弃
qt与web端数据交互
对于代码层面来说,最大的修改就是由同步调用改为异步回调,qt与js的相互调用需要进行部分调整
1.qt调用js
之前代码中调用js能同步获得返回值,现在需要新增同步调用函数去替换原有逻辑,通过QEventLoop实现,谨慎调用
// 异步调用
void MainWindow::runJs(const QString &jsStr)
{
m_view->page()->runJavaScript(jsStr);
}
// 同步调用
QVariant MainWindow::runJsSync(const QString &jsStr)
{
m_view->page()->runJavaScript(jsStr, [&](const QVariant &res){
m_jsRes = res;
emit sig_runJsFinished();
});
QEventLoop loop;
connect(this, &MainWindow::sig_runJsFinished, &loop, &QEventLoop::quit);
loop.exec();
return m_jsRes;
}
2.js调用qt
升级为QWebEngine后,js调用qt的槽函数需要通过QWebChannel实现,槽函数声明时要为"public slots",不然js无法调用。
qt代码
m_view=new QWebEngineView(this);
//创建通道对象用于与JS交互
m_channel = new QWebChannel(this);
WebChannelObject* webObj = new class WebChannelObject(this);
m_channel->registerObject("webObject", webObj);
// 注册后析构前要取消注册deregisterObject,不然debug会报错
m_view->page()->setWebChannel(m_channel);
class WebChannelObject : public QObject
{
Q_OBJECT
public:
WebChannelObject(QObject *parent);
signals:
void sig_tips(const QString &name);
public slots:
void slot_tips();
void slot_getCoordinate(QString lon,QString lat);
};
WebChannelObject::WebChannelObject(QObject *parent)
: QObject(parent)
{
}
void WebChannelObject::slot_tips()
{
emit sig_tips("hello, world!");
}
void WebChannelObject::slot_getCoordinate(QString lon, QString lat)
{
qDebug()<<lon<<lat;
}
js代码
js中需要包含qwebchannel.js,安装QWebEngine模块就附带的。可以全局搜索,然后拷贝到html的同级目录下
<script src="qwebchannel.js"></script>
// 创建通道对象并设置全局变量
new QWebChannel(qt.webChannelTransport, function (channel) {
window.webObj = channel.objects.webObject; //对象名与QT中一致
});
map.addEventListener("click", function (e) {
// 调用qt
webObj.slot_getCoordinate(e.point.lng, e.point.lat);
});
3.qt通过信号调用js函数
qt调用js也可以不使用runJavaScript,而是借助QWebChannel实现
将上述js代码修改一下,增加信号与函数的关联
// 创建通道对象并设置全局变量
new QWebChannel(qt.webChannelTransport, function (channel) {
window.webObj = channel.objects.webObject; //对象名与QT中一致
window.webObj.sig_tips.connect(function (name) {
alert(name);
});
});