对于熟悉Web的人都知道Web实现的界面更加炫酷,css样式以及js的强大功能,能够让界面发挥最大的视觉效果,下面就来说一下在Qt中如何加载Html并且实现与Js的交互。
首先我们准备这样一个Html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="map1" style="width:500px;height:500px;margin:0px;padding:0px;background-color:red;"></div>
</body>
</html>
在Qt中要想加载Html页面,需要使用到QWebEngineView这个对象,该对象需要引入头文件。
QWebEngineView集成了浏览器的webkit内核和google的v8引擎
- Qt5.4之前:webkitwidgets模块 - QWebView
- Qt5.4之后:webenginewidgets模块 - QWebEngineView
在.pro文件中加上QT += webenginewidgets
#include <QWebEngineView>
QWebEngineView负责加载Html内容并进行显示,创建QWebEngineView实例,使用load()加载html文件。
QWebEngineView *m_QWebEngineView = new QWebEngineView(this);
m_QWebEngineView->load(QUrl::fromLocalFile(mapPath));//加载html
this->layout()->addWidget(m_QWebEngineView);
如果只是显示Html页面,没有Js交互,则以上内容就完成了。但如果需要与Html页面中的Js进行交互则需要使用到另外一个对象:QWebChannel,引入头文件。
在.pro文件中加上QT += webenginewidgets webchannel
#include <QWebChannel>
QWebChannel是Qt与Js通信的通道,通过注册Js上下文实现响应Js调用Qt槽函数,创建一个类文件,定义槽函数用于接收Js的调用。
#ifndef JSCONTEXT_H
#define JSCONTEXT_H
#include <QObject>
#include <QMessageBox>
/**
* qt与js交互的上下文类
* js通过槽函数实现与qt进行数据交互,在此类中定义接收js参数的槽函数
*/
class JsWebContext : public QObject
{
Q_OBJECT
public:
explicit JsWebContext (QObject *parent = nullptr);
signals:
public slots:
void jsCallMe(const QString &msg);
};
#endif // JSCONTEXT_H
除此之外,还需要Qt官方提供的qwebchannel.js文件,如果在安装Qt时选择了安装源码,则在本地安装路径中可以找到这个文件
该js文件需要通过Qt注入的形式加载到Html中,否则会无法识别,由于Js需要使用的Html元素有可能在还没有加载完成,所有最好是在等待页面加载完成后进行写入,通过绑定加载完成信号来完成。
connect(m_QWebEngineView, &QWebEngineView::loadFinished, this, &MapForm::slt_webLoadFinish);
QWebEngineView在加载完Html页面后会发送loadFinished信号,在其槽函数中,通过读取qwebchannel.js和自定义的js文件,注入到Html页面中
void MapForm::slt_webLoadFinish() {
QFile filewebjs(":/Resources/qwebchannel.js");//引入qt自带的js文件
QFile customjs(":/Resources/custom.js");//引入
if (!filewebjs.open(QIODevice::ReadOnly)||!customjs.open(QIODevice::ReadOnly)) {
return;
}
QByteArray bywebjs = filewebjs.readAll();
QString strreportjs = customjs.readAll();
bywebjs.append(strreportjs);
filewebjs.close();
customjs.close();
webchannel = new QWebChannel(m_QWebEngineView);//创建通道
m_JsContext = new JsContext();//创建js上下文
webchannel->registerObject("m_JsContext", m_JsContext);
m_QWebEngineView->page()->setWebChannel(webchannel);
m_QWebEngineView->page()->runJavaScript(bywebjs);
QString fun = QString("setWinSize('%1','%2')").arg(this->width()).arg(this->height());
m_QWebEngineView->page()->runJavaScript(fun);
}
custom.js中的函数如下
// 定义webchannel对象并初始化===========================
var webobj;
new QWebChannel(qt.webChannelTransport, function(channel)
{
webobj = channel.objects.webContext;
window.foo = webobj;
});
//设置窗体宽高,Qt中调用的函数
function setWinSize(w,h){
var m = document.getElementById('map1');
m.setAttribute("style","width:"+w+"px;height:"+h+"px");
}
// 点击网页中的按钮调用Qt中的槽函数
var btn = document.getElementById("btn");
btn.onclick = function()
{
sendMsg("传递参数到Qt槽函数");
}
// 向qt发送文字消息
function sendMsg(msg)
{
if(typeof webobj == 'undefined')
alert("context对象获取失败!");
else
webobj.jsCallMe(msg);//onMsg是Qt中的槽函数
}
总结:在Qt中定义槽函数,使用qwebchannel.js提供的功能调用Qt的槽函数传递参数,Qt中通过m_QWebEngineView->page()->runJavaScript(fun);调用Js文件中的函数