对于熟悉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文件中的函数