有关Qt的WebEngine模块与JS交互的研究



  • 0_1524455491639_444.png
    最近几年Web和桌面混合应用逐渐流行起来,Qt也顺应形势,在2014年12月推出了WebEngine模块。它的作用就是让开发桌面/WEB混合应用程序更加方便。之前我了解了一些WebEngine的内容,也做了一些小的demo,但是直到前些日子,我对WebEngine强大的功能了解一点点。一些特殊的场景依然需要开发者更加努力完善才行,比如说:

    1. 浏览器和桌面应用的交互
      通过点击浏览器的内容转到桌面特定的功能或者点击桌面的菜单启动浏览器并且进行一些设置,这些需要涉及到WebEngine和Javascript交互的知识;
    2. 为浏览器添加特定的插件以便在输入含有特定的scheme的时候,启动本地相关的功能。比如ed2k://这样的链接。这里要涉及到一个浏览器的URL处理handler这样的处理步骤。

    现在很多的软件都支持内置网页,比如说迅雷软件,还有WPS,这些都支持在内部载入浏览器。也很好地实现了“软件+内容”的统一处理。带着这些问题,我们也尝试着了解WebEngine,并且使用WebEngine来实现相应的功能。



  • 一个非常常见的需求就是需要满足WebEngine中的html元素和Qt的其它元素的交互。因为如果只套了WebEngine,数据只在Chromium中的v8引擎中流动,和Chrome浏览器无异。我们软件的开发主要看重的是和其它的程序进行联动。比如说软件内链接可以本地启动一个轻量级的浏览器,或者浏览器的内容点击可以让本地程序进行响应。这一部分我想是WebEngine精髓的地方,好在Qt团队想到了这一点,可以使用WebChannel这个模块来实现这样的目的,和以前操作QtWebkit那一套不同,使用WebChannel通过信号和槽将WebChannel和本地C++对象连接起来,通过JS的事件机制将WebChannel和JS对象连接起来,从而建立了联系,这样做有利于解耦C++和WebEngine,让其具有更大的可操作移植性。

    好了,开始拿官方的例子做研究了,我们选择先从WebChannel入手,查看官方的例子:standalone
    0_1524384025356_d8484c85-83e0-4a1e-a000-bc9f6a0aed5d-image.png

    我们发现它包含了几个文件:

    core.h
    core.cpp
    dialog.h
    dialog.cpp
    main.cpp
    shared/qwebchannel.js

    值得注意的是qwebchannel.js文件,它以模块化的方式在js前端(或者后端)搭建了桥梁,让Qt对象通过传输协议(很大程度上是websocket)暴露在js中并且得以使用。

    例子也较为简单,通过客户端建立本地的QWebSocketServer来监听12345端口,并且让客户端的QWebSocket和浏览器的WebSocket(原生)同时监听localhost:12345端口。这样可以实现双端通信。值得注意的是,客户端和网页端都使用了WebChannel来建立起联系——客户端使用的是WebChannel的C++接口方法,而网页端使用的是qwebchannel.js方法。
    0_1524385057615_8431ace6-5420-48d6-bd88-b6f124985529-image.png

    这个例子简单展示了WebChannel的使用,但我认为此处的WebChannel其实是多余的,只通过WebSocket就可以建立客户端和网页的连接。



  • 每次都想用html写界面,然后后台用C++。
    但是Qt WebEngine总是用不好
    有个叫CEF的东西,好像用的人挺多的



  • @大黄老鼠 我也考察了cef。主要是cef这块儿有三点:

    1. 下载需要翻墙,如果没有梯子的话,都没办法下载下来。
    2. 文档较少,我能知道的文档主要来自于博客介绍。
    3. 如果是自己制作软件嵌入浏览器,可能选择MFC + cef、Qt + cef,或者是其它基于各种语言的库 + cef。如果要处理多进程的问题,还是需要非常具有经验的开发者才行。简而言之,学习门槛稍微高。

    WebEngine慢慢在发展,一些以前没有暴露的接口现在已经暴露出来了。而且有Qt公司的维护,我想至少作为入门是没有问题的。

    他们俩都不好的地方就是库太大了。随随便便就是50M以上。


Log in to reply
 

走马观花

最近的回复

  • @qyvlik 这个例子可否提供学习一下?

    read more
  • 113.jpg
    1、什么是lambda表达式,什么是闭包?
    lambda表达式即lambda函数,也就是匿名函数。

    lambda表达式在C++中包含了
    []表示捕获
    ()是函数的参数,需要指定类型
    ->type是返回的类型,可以省略,如果编译器无法推出类型的话可以强制编写
    {}是函数体。

    lambda可以被声明为mutable的,作用是将捕获的内容进行改变。
    闭包是函数的定义以及定义函数时提供的环境,总称为闭包。lambda函数也是一种闭包。
    lambda本身是匿名函数,而捕获语句则是提供了定义函数时提供的环境。

    2、什么是右值引用?
    右值引用相对与左值引用而言的。左值即=运算符左边的变量,右值是=运算符右边的常量或变量。由此可以看出,
    右值引用指的是对常量或变量的引用。它的用途包含了移动语义和完美转发。
    移动语义就是弥补了C++历史在处理变量传递时丢失的一种语义。它和值传递、引用传递一样,是变量传递的方式之一。
    如果没有移动语义,为了将一个类的实例传递给另外一个实例,就需要额外地进行构造、赋值、销毁的操作。
    对于一些比较复杂的变量,的确是非常耗时并且消耗大的操作。(浪费指令时间、浪费内存)

    对于这样的函数返回:
    vector<string> str_split(const string& s) {
    vector<string> v;
    // ...
    return v; // v是左值,但优先移动,不支持移动时仍可复制。
    }

    标准要求先调用移动构造函数,如果不符合那么再调用拷贝构造函数。所以可以轻松地写出这种写法而不必担心效率问题。
    同时,现代编译器都会对返回值进行优化,成为RVO以及NRVO。所以不用太担心会多调用构造析构函数。

    对于完美转发,C++对于引用的转发有规则。传统的C++是无法对引用进行再引用的。但是现代的C++放宽了它的使用范围。
    只有右引用右值的时候,才会产生右引用。这也称为引用折叠。

    3、auto关键字的作用是什么?
    auto关键字为的是能够让编译器自动推导类型。自C++98之后,编译器对类型的推导变得越来越智能了。
    而我们在编写复杂代码的时候,冗长的类型不仅容易出错,有时也不容易人工推导出类型。
    因此auto可以简化我们的任务量,让类型的推导交给编译器完成。
    除了auto外,我们还可以使用decltype()来让编译器推导类型。

    read more
  • 我感觉比起《Physically Based Rendering Technique》,还是《Ray Tracing in a Weekend》更容易上手,因为慢慢地能够做出一个渲染效果,这个是有成就感的。🎓

    read more
  • G

    北京名律免费法律咨询,解决您的法律困扰,如果您眼下没有遇到法律上的问题,也可以留一位大律师的联系方式以备不时之需!ccfd91efc3a6b2ed0e79054d2248eed.jpg bf6015b383483f1fe83cdcfd130fc6b.jpg 2f347879129add1096bf3424edbe517.jpg

    read more

关注我们

微博
QQ群