赞
踩
官方文档:https://doc.qt.io/archives/qt-5.11/qtwebengine-overview.html
翻译文档:Qt5.9 WebEngine 概述 - 一花一世界,一叶一乾坤 - 博客园
从Qt5.5开始,Qt WebKit模块被废弃,被Qt WebEngine模块取代,Qt WebEngine模块提供了一个web浏览器的API(基于谷歌浏览器内核,libcef的库), 在不使用本地浏览器的情况下,它可以很容易地把Web内容嵌入到Qt应用程序中,Qt WebEngine为渲染HTML,XHTML和SVG文档,,使用CSS和JavaScript, 提供了C++类和QML类型。
Qt WebEngine的功能分成下列模块:
注意的是亮点,1、建议使用qt5.8之后的版本,网上说对webengine支持的好一点前面的版本可能会有bug。2、vs2015的编译器,网上说只能使用qt-msvc版本+vs2015编译器,我只试了这个版本,好使,其他的版本,没使用过不保证没问题。
安装选项:1、command tools for visual c++2015 2、python tools for visual studio
http://219.83.160.146:5476/%E8%BD%AF%E4%BB%B6%E5%8C%85/win10sdk/我自己存的
Windows SDK - Windows app development
安装选项:只要装debugging tools for windows
构建套件的时候选择vs的编译器就可以了,debug选择win10sdk中的调试器
打开Qt新建一个项目,在.pro文件里面添加QT += webenginewidgets之后跟着下面这个链接走就行了
QT webengine 例子_small house-CSDN博客 很简单,就不多叙述了,网上的资料也很多。
我在使用过程中经常会遇到new一个对象但是提示链接错误的情况,其实代码是对的,可能是Qt ide的原因,可以试试把编译的目录全部删了,之后重新编译,有可能会修复哦。
这一块很重要,也是我研究的比较多的地方,先给出两篇对我研究过程最有用的文档。
Communication between C++ and Javascript in Qt WebEngine//这一篇是最有用的
QWebEngineView与js交互_Keep It Simple, Stupid-CSDN博客
最清晰Qt与JS通过qwebchannel交互例子_小猿一枚的专栏-CSDN博客
Qt调研js:
这一步很简单,只要跑runJavaScript这个函数就好了,我也没用再多研究下去,因为我的程序是以web页面为主,Qt只是一个壳子,所以基本上都是js去调用我的函数。
- void JsContext::sendMsg(QWebEnginePage* page, const QString& msg)
- {
- page->runJavaScript(QString("recvMessage('%1');").arg(msg));
- }
js调用Qt:
需要用到Qt注册一个js的对象,或者说Qt和js使用同一个对象,
qwebchannel.js是Qt提供的js方法,可以在这里下载:https://code.csdn.net/tujiaw/webengineview/tree/master/qwebchannel.js
里面提供了一些方法让qt和js共同使用一个对象。
1、需要把上面那个文件qwebchannel.js下载到html同级目录下
2、自己的js,这里面的init函数很重要,成功引用官方的qwebchannel.js之后就会找到qt对象,之后context = channel.objects.context;这个就说明js与一个叫”context“的对象绑定在一起,后面Qt中会使用到这个context
context.someattributeChanged.connect(updateattribute);下面这句话是表面给context这个对象设置一个回调函数,只要后面Qt中会使用到这个回调函数。
- var context;
- // 初始化
- function init()
- {
- var updateattribute=function(text)
- {
- alert(text);
- //$("#attrid").val(text);
- }
- if (typeof qt != 'undefined')
- {
- new QWebChannel(qt.webChannelTransport, function(channel)
- {
- context = channel.objects.context;
- context.someattributeChanged.connect(updateattribute);
- }
- );
- }
- else
- {
- alert("qt对象获取失败1!");
- }
- }
-
- // 接收qt发送的消息
- function recvMessage(msg)
- {
- alert(msg);
- }
-
- // 向qt发送消息
- function sendMessage(msg)
- {
- if(typeof context == 'undefined')
- {
- alert("context对象获取失败2!");
- }
- else
- {
- context.onMsg(msg);
- //context.setsomeattribute(msg);
- //updateattribute(context.m_someattribute);
- }
- }
- // 控件控制函数
- function onBtnSendMsg()
- {
- var cmd = document.getElementById("待发送消息").value;
- sendMessage(cmd);
- }
- init();
3、html,写一个最简单的html程序,引用上面的两个js文件,实现一个按钮点击之后出发sendMessage这个函数,发送一个字符串过去。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta http-equiv=Content-Type context="text/html;charset=utf-8">
- <title>webchannel test</title>
- </head>
- <body>
- <p>webchannel test</p>
- <script type="text/javascript" src="./qwebchannel.js"></script>
- <script type="text/javascript" src="./msgutils.js"></script>
- <input id="待发送消息" type="text" name="msgText" />
- <input type="button" value="send msg" onclick="onBtnSendMsg()" />
- </body>
- </html>
4、Qt端new一个Jscontext对象和前面js里的context对象绑定起来,很简单的几句话,在webchannel上绑定就好了。
- JsContext *jsContext = new JsContext();
- QWebChannel *webChannel = new QWebChannel();
- Webpage *webPage = new Webpage();
- webChannel->registerObject("context", jsContext);
- webPage->setWebChannel(webChannel);
5、接收回调函数,在c++中实现下面这个类Jscontext,用来和js交互的对象,注意的是里面的public slots里面有一个OnMsg函数,如果在js里面被调用context.onMsg(msg);那么在Qt里面就会有相应,这一点很简单,但是如何使用上面实现的回调函数呢?
需要声明一个信号signal:void someattributeChanged(const QString &attr);然后再emit someattributeChanged(m_someattribute);触发他即可,触发的时候将自己的参数带进去,可以是json字符串。这里有个很重要的点也是我之前遇到的坑,就是Communication between C++ and Javascript in Qt WebEngine这篇文档中没写明白的,在使用信号的时候void someattributeChanged(const QString &attr);里面必须要用const不然的话,js里面收的对象都是NULL。说明白之后我这边的功能基本都能实现了,如果说有小伙伴想要实现更加精细的功能,js和Qt的对象共享数据,那么在类里面加这个Q_PROPERTY(QString someattribute MEMBER m_someattribute NOTIFY someattributeChanged)之后,定义的私有数据应该就能共享了,具体可以看上面那篇英文文档。
- #ifndef JSCONTEXT_H
- #define JSCONTEXT_H
-
- #include <QObject>
- #include <QWebEnginePage>
- #include <QString>
- #include "vcdlog4qt.h"
-
- class JsContext : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(QString someattribute MEMBER m_someattribute NOTIFY someattributeChanged)
- public:
- explicit JsContext(QObject *parent = 0);
- void sendMsg(QWebEnginePage* page, const QString& msg);
-
- private:
- QString m_someattribute;
-
- signals:
- void recvdMsg(const QString& msg);
- void someattributeChanged(const QString &attr);
-
- public slots:
- void onMsg(const QString& msg);
- void setsomeattribute(QString attr);
-
- };
-
- #endif // JSCONTEXT_H
- #include "jscontext.h"
-
- JsContext::JsContext(QObject *parent) : QObject(parent) {
- VcdLog4Qt::getInstance()->info("new jscontext");
- }
-
- void JsContext::sendMsg(QWebEnginePage* page, const QString& msg)
- {
- page->runJavaScript(QString("recvMessage('%1');").arg(msg));
- }
-
- void JsContext::onMsg(const QString &msg)
- {
- emit recvdMsg(msg);
- }
-
- void JsContext::setsomeattribute(QString attr)
- {
- m_someattribute = attr;
- emit someattributeChanged(m_someattribute);
- }
有一个问题就是,webchannel在一个页面上只能开启一个通道,如果,页面多个按钮想要同时绑定这个对象进行同时传输数据是不行的,需要用总的通信通道通过协议分发给每个控件来做。
下载文件我使用了官方给的方法QWebEngineDownloadItem 这个类里面实现了下载的信号以及方法,直接用即可,也可以自己实现下载,当页面点击的时候通过上面的通信的办法告诉Qt下载的地址,然后进行下载,但是下载之后的进度上面的都需要自己去实现。
connect(webPage->profile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)),this, SLOT(downloadRequested(QWebEngineDownloadItem*)));首先绑定下面这个信号,当页面有下载动作的时候会触发这个信号,下面是触发下载之后要做的事情,下载触发之后绑定下面两个信号downloadProgress,finished,在过程中会通知你进度(前端可以实现进度条)然后结束的时候也会通知你。一定要写download->accept()有了这个之后下载才会进行。
- void MainWindow::downloadRequested(QWebEngineDownloadItem* download)
- {
- download->accept();
- connect(download.data(), SIGNAL(downloadProgress(qint64,qint64)),
- this, SLOT(downloadProgress(qint64,qint64)));
- connect(download.data(), SIGNAL(finished()),
- this, SLOT(finished()));
- }
注意:重要的点,如果说页面下载动作是当前页面保存链接,那么这个信号是会被触发的,但是如果页面是正常的下载,那么在浏览器里面效果是打开一个新的页面进行下载的,这样的话这个信号是不会被触发的,因为这个下载信号只绑定了当前页面,如果要实现触发,需要在新的页面中实现绑定才行,这也是我刚开始遇到的坑,分享给大家。
有兴趣的同学可以去看看Qt里面用webengine实现的浏览器,会学到很多哦。
最后祝大家学习愉快,有问题或者有需要源码的小伙伴可以私聊我哈。
里面也有log4qt的使用方法大家可以借鉴。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。