Communication between C++ and Javascript in Qt WebEngine

admin January 31, 2018 0

As Qt WebKit is replaced by Qt WebEngine(you can refer to this postabout porting issues), accessing html elements from C++ directly becomes impossible. Many works originally done by QWebKit classes are now transferred to javascript. Javascript is used to manipulate web content. And you need to call runJavaScript from C++ code to run javascript on the web page loaded by QWebEngineView.To get web elements, a communication mechanism is invented to bridge the C++ world and the javascript world. The bridging mechanism is more than obtaining the values of web page elements. It provides the ways in which C++ code can call javascript functions, and javascript can invoke C++ functions as well.The values of variables can also be passed from C++ to javascript, and vice versa. Let’s consider the following application scenarios:

javascript code calls C++ function

C++ code should provide a class which contains the to-be-called function(as a slot), then register an object of this class to a QWebChannelobject, and set the web channel object to the web page object in the QWebEngineView

  1. class WebClass : public QObject
  2. {
  3. Q_OBJECT
  4. public slots:
  5. void jscallme()
  6. {
  7. QMessageBox::information(NULL,"jscallme","I'm called by js!");
  8. }
  9. };
  10. WebClass *webobj = new WebClass();
  11. QWebChannel *channel = new QWebChannel(this);
  12. channel->registerObject("webobj", webobj);
  13. view->page()->setWebChannel(channel);

To invoke the C++ function jscallme, javascript should new an instance of QWebChannel object.

  1. new QWebChannel(qt.webChannelTransport,
  2. function(channel){
  3. var webobj = channel.objects.webobj;
  4. window.foo = webobj;
  5. });

QWebChannel is defined in qwebchannel.js(you can find this file in the example folder of Qt installation directory) so the script should be loaded first. In the function passed as the second parameter of function QWebChannel, the exposed object from C++ world(webobj in C++) channel.objects.webobj is assigned to the javascript variable webobj, and then assigned to window.foo so you can use foo elsewhere to refer to the object. After the function is executed, javascript can call the C++ slot function jscallme as follows:

  1. foo.jscallme();

Pass data from javascript to C++

We’ve known how to call C++ function from javascript. You should be able to figure out a way to pass data from javascript to C++, i.e., as parameter(s) of function. We re-implement jscallme as follows:

  1. void jscallme(const QString &datafromjs)
  2. {
  3. QMessageBox::information(NULL,"jscallme","I'm called by js!");
  4. m_data=datafromjs;
  5. }

, and invoking of the function from js would be:

  1. foo.jscallme(somedata);

Note that the “const” before the parameter can not be omitted, otherwise, you will get the following error:
Could not convert argument QJsonValue(string, “sd”) to target type .

Although data can be passed as parameters of function, it would be more convenient if we can pass data by setting an attribute of an object like:

  1. foo.someattribute="somedata";

We expect after the code is executed, “somedata” will be stored in a member variable of the exposed object (webobj) in C++. This is done by delaring a qt property in C++ class:

  1. class WebClass : public QObject
  2. {
  3. Q_OBJECT
  4. Q_PROPERTY(QString someattribute MEMBER m_someattribute)
  5. public slots:
  6. void jscallme()
  7. {
  8. QMessageBox::information(NULL,"jscallme","I'm called by js!");
  9. }
  10. private:
  11. QString m_someattribute;
  12. };

Now if you execute foo.someattribute=”somedata” in javascript, m_someattribute in C++ will be “somedata”.

Pass data from C++ to javascript

We can send data from C++ to javascript using signals. We emit a signal with the data to send as the parameter of the signal. Javascript must connect the signal to a function to receive the data.

  1. class WebClass : public QObject
  2. {
  3. Q_OBJECT
  4. Q_PROPERTY(QString someattribute MEMBER m_someattribute)
  5. public slots:
  6. void jscallme()
  7. {
  8. QMessageBox::information(NULL,"jscallme","I'm called by js!");
  9. }
  10. void setsomeattribute(QString attr)
  11. {
  12. m_someattribute=attr;
  13. emit someattributeChanged(m_someattribute);
  14. }
  15. signals:
  16. void someattributeChanged(QString & attr);
  17. private:
  18. QString m_someattribute;
  19. };
  1. var updateattribute=function(text)
  2. {
  3. $("#attrid").val(text);
  4. }
  5. new QWebChannel(qt.webChannelTransport,
  6. function(channel){
  7. var webobj = channel.objects.webobj;
  8. window.foo = webobj;
  9. webobj.someattributeChanged.connect(updateattribute);
  10. });

The line “webobj.someattributeChanged.connect(updateattribute)” connects the C++ signal someattributeChanged to the javascript function updateattribute. Note that although updateattribute takes one parameter “text”, we did not provide the parameter value in connect. In fact, we do not know the parameter value passed to updateattribute until the signal is received. The signal is accompanied by a parameter “attr” which is passed as the “text” parameter of updateattribute. Now, if you call webobj->setsomeattribute(“hello”), you will see the value of the html element with id “#attrid” is set to “hello”. Note that although we connect the member m_someattribute to the qt property someattribute in the above example, it is not a required step. The signal mechanism alone can realize the delivery of data.
We can make things even simpler by adding the NOTIFY parameter when declaring the someattribute property.

  1. class WebClass : public QObject
  2. {
  3. Q_OBJECT
  4. Q_PROPERTY(QString someattribute MEMBER m_someattribute NOTIFY someattributeChanged)
  5. public slots:
  6. void jscallme()
  7. {
  8. QMessageBox::information(NULL,"jscallme","I'm called by js!");
  9. }
  10. signals:
  11. void someattributeChanged(QString & attr);
  12. private:
  13. QString m_someattribute;
  14. };

Now, if you call webobj->setProperty(“someattribute”,”hello”) somewhere in C++, the signal “someattributeChanged” is automatically emitted and our web page gets updated.

C++ invokes javascript function

This is much straightforward compared with invoking C++ function from js. Just use runJavaScript passing the function as the parameter as follows:

  1. view->page()->runJavaScript("jsfun();",[this](const QVariant &v) { qDebug()<<v.toString();});

It assumes the jsfun is already defined on your web page, otherwise, you have to define it in the string parameter. The return value is asynchronously passed to the lambda expression as the parameter v.

Now, back to the question raised at the beginning of the post: How to get the value of an html element in C++? It can be done as follows:

  1. view->page()->runJavaScript("function getelement(){return $('#elementid').val();} getelement();",[this](const QVariant &v) { qDebug()<<v.toString();});

It uses jQuery functions so make sure jQuery lib is running on your web page.

Communication between C++ and Javascript in Qt WebEngine(转载)的更多相关文章

  1. javascript - C++, Qt, QtWebKit: How to create an html rendering window so that your application would get callbacks from JS calls? - Stack Overflow

    javascript - C++, Qt, QtWebKit: How to create an html rendering window so that your application woul ...

  2. Qt WebEngine版本要求

    WebEngine是Qt5.4之后加入的新特性,用Qt WebEngine取代之前的Qt Webkit http://wiki.qt.io/QtWebEngine windows版本 windows版 ...

  3. 解决 “Project ERROR: Unknown module(s) in QT: webengine”以及“Your MaintenanceTool appears to be older than 3.0.2. .” 的办法

    1.环境 Windows10,Qt5.8.0 2.问题描述 需要使用到WebEngineView组件,在工程.pro中增加webengine后,Qt Creator应用程序输出中打印了 Project ...

  4. linux 下Qt WebEngine 程序打包简单记录

    本次记录仅作参考. 程序说明: 程序是一个编解码器控制管理的工具,使用到的库有:Qt的WebEngine.OpenGL模块.poco库.libmicrohttpd.libcurl.libvlc.同时程 ...

  5. Qt WebEngine 网页交互

    环境:Qt5.7.0,VS2013 一.简单介绍 从 Qt5.4 开始已经去掉 Qt WebKit 模块了,使用的是 chrome 内核封装的 QtWebEngine,浏览器相关的类有以下几个: QW ...

  6. Qt Unknown module(s) in QT: webengine

    到今天位置好像Qt 出到了5.10还是5.9.x吧,本身是用MSVC 5.7.0本身就有支持 webengine这个模块 然后跟风升级了5.9.1,公司项目不用qt框架了用VC渣渣6.0.....然后 ...

  7. qt添加cef库嵌入web,linux 下Qt WebEngine 程序打包简单记录

    http://www.cnblogs.com/oloroso/p/6051631.html http://www.cnblogs.com/oloroso/p/6149000.html

  8. 深入理解JavaScript的变量作用域(转载Rain Man之作)

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  9. javascript keycode大全【转载】

    keycode    8 = BackSpace BackSpace keycode    9 = Tab Tabkeycode   12 = Clearkeycode   13 = Enterkey ...

随机推荐

  1. xftp上传文件到虚拟机linux失败问题

    如果想通过xftp上传文件到虚拟机linux时,可能会产生上传失败的问题 原因: 因为有些文件是只可读,所以要修改文件权限,可读可写,才可以上传成功. 解决方法: 第一种方法:用xftp连接虚拟机后, ...

  2. 高效C++无锁队列实现-moodycamel::ConcurrentQueue

    国外一牛人做的,支持多平台,支持多线程写.多线程读,并可指定读写token,转载过来. 感觉作者也时刻维护着他这个项目,我提了一些问题,每次都会及时得到答复,而且回复得非常认真仔细,非常赞! 链接地址 ...

  3. Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name) 中文显示乱码

    如果file.Name为中文则乱码.解决办法是方法1:response.setHeader("Content-Disposition", "attachment; fil ...

  4. LC 789. Escape The Ghosts

    You are playing a simplified Pacman game. You start at the point (0, 0), and your destination is(tar ...

  5. 【Linux】【二】linux 压缩文件(txt)、查看压缩文件内容、解压缩文件、

    通过Xshell 压缩文件.解压缩文件 gzip tools.txt 压缩[tools.txt]文件 zcat tools.txt.gz   查看压缩文件[tools.txt.gz]内容 gunzip ...

  6. 2单表CRUD综合样例开发教程

    东软集团股份有限公司 基础软件事业部 单表CRUD综合样例开发教程 东软机密 tui 更改履历 版本号 更改时间 更改的 图表和章节号 状态 更改简要描述 更改申 请编号 更改人 批准人 V1.0 2 ...

  7. apache thrift 入门(一)

    1.简介 Apache Thrift软件框架,是用来开发可扩展的跨语言的软件服务.通过软件堆栈和代码生成引擎相结合的方式来构建服务,使C++, Java, Python, PHP, Ruby, Erl ...

  8. 认识一下 Kafka

    Kafka 基本概述 什么是 Kafka Kafka 是一个分布式流式平台,它有三个关键能力 订阅发布记录流,它类似于企业中的消息队列 或 企业消息传递系统 以容错的方式存储记录流 实时记录流 Kaf ...

  9. 5分钟快速安装Redmine项目管理软件

    公司还在使用Excel.project.word来管理项目吗?时间一长.项目参与的人多.就出现了断断续续无法连续跟踪的问题.终于忍受不了公司这种陈旧的项目管理手段了,于是花了一些时间研究了市面上常见的 ...

  10. C学习笔记-结构体

    结构体的定义和初始化 结构体是简单数据类型的综合 struct man { char name[100]; int age; }; struct man m = { "tom", ...