当前位置: 首页 > news >正文

QT网页 webengine / CEF

QT + WebEngine

官方文档

WebEngine 架构:

在这里插入图片描述

能看到 WebEngine 有一个核心模块是基于 Chromium 构造的,通过使用 Chromium 的Blink渲染引擎和V8 JavaScript引擎来处理和渲染Web内容,并将这些底层技术封装为一系列高级的C++类和接口,以便开发者可以将Web内容嵌入到Qt应用程序中。

  1. WebEngine Widgets 模块:主要是针对于桌面应用,提供了用于将Web内容嵌入到Qt应用程序中的窗口和小部件, 可以用于各种应用程序来加载web内容。
    在这里插入图片描述

主要架构如上图所示,主要提供了一些组件:

  • QWebEnginePage:一个代表Web页面的类,它包含了页面的内容、状态和功能。它可以执行JavaScript代码、处理表单、捕获页面截图等。
  • QWebEngineView:一个用于展示Web页面的小部件,它是QWebEnginePage的可视化容器。它可以加载URL、导航历史、缩放页面等。
  • QWebEngineProfile:一个表示浏览器配置文件的类,它包含了缓存、Cookie和安全策略等设置。它可以用于实现多用户浏览器或隐私浏览功能。
  • QWebEngineSettings:一个表示浏览器设置的类,它包含了字体、颜色、JavaScript和插件等选项。它可以用于调整页面的渲染效果和功能。
  • QWebEngineScript:执行 JavaScript 脚本的类,用于向网页中注入并执行自定义的 JavaScript 脚本来添加新功能或修改现有的功能。
  • QWebEngineHistory:管理浏览历史的类,它提供了对浏览历史记录的访问和操作,其中每个历史记录项都由 QWebEngineHistoryItem 类表示。
  • WebEngineAction:表示对网页的操作,由WebEngineView::action()方法返回,包含相关的一些信息;

一个QWebEngineView 实例有一个 QWebEnginePage. QWebEnginePage有一个QWebEngineHistory和一些用于操作页面的QAction对象。每一个QWebEnginePage都属于一个QWebEngineProfile, QWebEngineProfile有一个页面设置的QWebEngineSettings, 一个在页面上运行脚本的QWebEngineScriptCollection, 一个访问HTTP cookies的QWebEngineCookieStore。

  1. WebEngine 模块:主要是针对用于QML。
    Qt WebEngine 除了没有单独访问的web引擎页面,包含的其他组件与Qt WebEngine Widgets相同,功能也是一致的。

  2. WebEngine Process:这是可执行文件,对应的是一个独立的用于渲染网页和执行JavaScript进程,用于增强安全性与内存隔离。
    网上有文章说“每个QWebEngineView或WebEngineView实例都会启动一个QtWebEngineProcess.exe进程”,在View对象过多的情况下会导致内存占用;
    但是在官方文档里没有找到相关描述,这个问题暂时未能确定;

  3. WebEngine 对 AMD 显卡支持性不好,在某些A系显卡下会显示不出来甚至闪退; 后续优化计划目前还没在网上搜到;另外嵌入的网页无法播放视频,要播放视频的话需要下载QT源码自己设置编译参数集成视频播放库;

  4. 对显卡有依赖,基于openGL,看网上说如果在显卡和显卡驱动不一致或是旧版版本下还有openGL,程序有可能出异常

QT 与 网页通信

  1. 通过 WebEnginePage 与网页通信
    通过 WebEngine 嵌入网页的方式与网页端的JS交互很容易,QWebEnginePage 自带了一个函数为 runJavaScript ,这个函数可以直接通知 JS 执行指定的函数,
    void QWebEnginePage::runJavaScript(const QString &scriptSource, const std::function<void (const QVariant &)> &resultCallback)

例如这个接口,第一个参数就是要调用的接口以及参数拼成的字符串,第二个参数是对应的回调。
这种方式用起来很方便,但是是单向的

  1. QWebChannel 双向通信
    QT提供了一种通道机制,可以让 JS 与 QT 通过对象建立连接, 然后进行通信;
    QWebChannel 提供了在 QT 和 HTML/JS 之间点对点的通信能力,通过向 HTML/JS 端的 QWebChannel 发布 QObject 的 派生对象,进而实现在 HTML/JS 端可以同步读取来自 Qt 端的 公共插槽 和 QObject 的 属性值 和 方法。在整个通信过程中,无需任何手动序列化传入的参数。所有 Qt 端的数据更新,都会自动且异步的触发 signal 并更新到 client 端。这个机制一般被称为对象模型,QObject 是这个模型的核心,而模型实现的基础就是靠的 QT 的 signal 和 slot 也就是信号槽机制。

这个机制主要分以下几步:

  • QT端 创建 HTML/JS 网页
  • JS端 创建 channel 对象,通过 channel 取到通信对象 QObject;
  • QT端 创建 channel 对象与通信用的 QObject 对象;
  • QT端 channel 与 网页对应的 QWebEngineView 绑定;
  • QT端 将 channel 与 QObject 对象绑定;
  • QT端/JS端 修改QObject属性,另一端对应的监听函数响应;

WebEngine 网页示例

源码见 QTWebtest_WebEngine
在示例代码里,我写了一个中间类名为 JS2QTBridge, 里面定义了两个字符串 m_jscontent 与 m_content;
通过 channel 将这个对象对 JS 与 QT 双向绑定,网页/QT界面上显示内容发生改变时给 QT/JS 发送对应信号,实现效果如:
在这里插入图片描述

其中在QT上点击按钮通知网页画图是用 runJavaScript 方法实现;
在网页点击饼图在QT弹出提示是通过调用 bridge 对象的函数实现;
两边输入框修改另一侧的显示区域一同变化是通过对 bridge 对象的成员变量与界面控件信号槽绑定实现;

QT + cef

CEF3使用多个进程运行。处理窗口创建、绘制和网络访问的主要进程称为浏览器进程,通常与宿主应用程序的进程相同,大多数应用程序的逻辑将在浏览器进程中运行。使用Blink引擎渲染HTML和JavaScript在单独的渲染进程中,相关的应用程序逻辑(如JavaScript绑定和DOM访问)将在渲染进程中运行。默认进程模型将为每个唯一源地址(scheme+domain)运行一个新的渲染进程。其他进程将根据需要生成,例如处理Flash等插件的插件进程和处理加速合成的GPU进程。另外浏览器进程中会进行窗口绘制,不是绘制HTML内容,而是承载网页内容的那个窗体,渲染进程则不会用来创建窗体。

<!-- 编译CEF参考 cef.md – >
cef解决方案中有多个工程:

  • ALL_BUILD与ZERO_CHECK:是cmake自动生成的辅助工程。
  • cef_gtest与ceftests:都是测试模块,这里不关心。
  • cefclient:一个包含CEF各种API演示的浏览器程序Demo。
  • cefsimple:一个简单的CEF浏览器程序Demo。
  • libcef_dll_wrapper:对libcef库的C++代码封装。上述cefclient与cefsimple都会用它。

可以移植 cefsimple 来实现一个简单的浏览器程序:

  • simple_app.h、simple_app.cc、simple_handler.h、simple_handler.cc 这四个文件拷到QT工程中;
  • simple_handler.h中的 PlatformTitleChange 定义注释掉;simple_handler.cc 的 OnTitleChange 对这个函数的调用也注释掉;
  • CEF.lib等相关库 以及 libcef_dll_wrapper.lib 拷贝到工程中,链接到QT工程里;
  • CEF的include文件夹拷贝到QT工程位置并引入;
  • CEF的 Resources 中的五项拷贝到QT编译出来的EXE的环境里;这些是网页渲染引擎需要的资源,不打包过去程序运行时会报错:icu_util.cc(224)] Invalid file descriptor to ICU data received.

QT 与 CEF 嵌入的网页通信有两种方式;

1. 使用 QWebChannel

这种方法与上面使用 webengine 时类似, 在QT 与 JS中声明channel, 通过将这个channel对象来作为中间通信的桥梁;
这种方式有一个优点是,可以通过 websocket 来让 Channel 监听指定的IP和端口来实现远程通信,而不仅仅局限于QT与它启动的web子进程;

2. 通过 CefRenderProcessHandler 的方法回调传递

  • virtual void OnWebKitInitialized() {}
    当 webkit 初始化完毕之后。在这个函数中,可以通过 CefRegisterExtension() 函数来注册JavaScript与C++代码之间的“映射”关系,官方管这种方式叫做扩展(Extension)

  • virtual void OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) {}
    JavaScript 上下文被创建以后,在这个函数中,可以为JavaScript中的 window 对象绑定属性和方法,官方将这种方式叫做 窗口绑定(window binding)

3. CEF网页通信示例

源码见 QTWebtest_CEF
在示例代码里,我写了一个网页,将这个网页用CEF展示在了QT窗口中,然后另外打开了一个QT对话框;
通过 channel 来在网页与对话框之间发送信息,展示效果如下:
在这里插入图片描述

CEF使用的一些问题:
不支持视频,需要自编译源码;原生的CEF是纯C代码,libcef_dll_wrapper才是在CEF的基础上封装的C++ API;
很大,我使用的版本的 libcef.dll 164MB, libcef_dll_wrapper.lib 33MB ,还有一些相关的加一起超200MB;
MD/MT属性支持的不好,CEF工程默认使用的是MT,其中用到的一些依赖库如cef_sandbox.lib都是MT编译的,使用MD编译会报错,要是改成MD需要自己下载相关源码编译;
多进程架构,WebEngine应该是一个view一个进程,如果只有一个view然后路径切换不会增加新的进程,CEF应该是每打开一次网页就会创建一个渲染进程;

相关文章:

QT网页 webengine / CEF

QT WebEngine 官方文档 WebEngine 架构&#xff1a; 能看到 WebEngine 有一个核心模块是基于 Chromium 构造的&#xff0c;通过使用 Chromium 的Blink渲染引擎和V8 JavaScript引擎来处理和渲染Web内容&#xff0c;并将这些底层技术封装为一系列高级的C类和接口&#xff0c;以…...

Golang笔试题:编写一个函数,接收一个整数参数n,输出n的阶乘结果

今天&#xff0c;我们开发的AI笔试题工具&#xff0c;ai扁食——AI程序员笔试系统给我出了中级Golang题目&#xff0c;就是这道题&#xff1a;《请编写一个函数&#xff0c;接收一个整数参数n&#xff0c;输出n的阶乘结果》&#xff0c;希望我写一个函数&#xff0c;输出n的阶乘…...

外包干了2个月,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

无涯教程-JavaScript - BINOM.DIST函数

描述 BINOM.DIST函数返回单个项二项式分布概率。 在具有固定数量的测试或试验的问题中使用BINOM.DIST。 当任何试验的输出只是成功或失败时 试验是独立的,并且 在整个实验中成功的概率不变的情况 语法 BINOM.DIST (number_s,trials,probability_s,cumulative)争论 Argu…...

linux定时重启tomcat

1.编辑重启Tomcat命令 首先编辑一个文件 vi my_restart.sh 然后输入&#xff1a; #!/bin/bash . /etc/profile tomcatPath"/opt/finereport/tomcat" binPath"$tomcatPath/bin" echo "[info][$(date %F %H:%M:%S)]正在监控tomcat&#xff0c;路径&a…...

在静态方法中访问@Value注入的静态变量!!

一、 静态变量 static修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;静态成员变量最大的特性&#xff1a;不属于某个具体的对象&#xff0c;是所有对象所共享的 简单来说&#xff1a;在某些类的对象中存在一些相同的成员变量&#xff0c;那么这种成员变量就可以设置…...

掌握这些算法,让你的编程之路更顺畅——重要算法解析

一个程序员一生中可能会邂逅各种各样的算法&#xff0c;但总有那么几种&#xff0c;是作为一个程序员一定会遇见且大概率需要掌握的算法。这些算法通常被广泛应用于日常编程工作中&#xff0c;是提升编程效率和解决实际问题的重要工具。本文将介绍几种十分重要的“必抓&#xf…...

flink集群与资源@k8s源码分析-总述

1 简介 集群和资源模块提供动态资源能力,是分布式系统关键基础设施,分布式datax,分布式索引,事件引擎都需要集群和资源的弹性资源能力,提高伸缩性和作业处理能力。本文分析flink的集群和资源的k8s模块,深入了解其设计原理,为开发自有的集群和资源组件做技术准备, 同时涉…...

LeetCode 0213. 打家劫舍 II:动动态规划

【LetMeFly】213.打家劫舍 II&#xff1a;动动态规划 力扣题目链接&#xff1a;https://leetcode.cn/problems/house-robber-ii/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味…...

VMware17 不可恢复错误mks解决方案

用的虚拟机VMware17版本&#xff0c;然后运行带HDR的unity程序&#xff0c;结果报错 网上找了很多解决方案&#xff0c;都没用。毕竟需要在不放弃虚拟机3D加速的情况下运行。 最终皇天不负有心人&#xff0c;亲测有效的方法&#xff1a; 在虚拟机名字.vmx文件里添加以下2行&a…...

【深度学习】 Python 和 NumPy 系列教程(廿五):Matplotlib详解:3、多子图和布局:subplot()函数

目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 2、3d绘图类型 3、多子图和布局 1. subplot()函数 简单示例 一、前言 Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年创建。它以简洁、易读的语法而闻名&#xff0c;并且具有强大的功能…...

计算机网络知识补充(1)

计算机网络:是一个将分散的&#xff0c;具有独立功能的计算机系统&#xff0c;通过通信设备和线路进行连接起来&#xff0c;由功能完善的软件实现资源共享和信息共享的系统&#xff0c;计算机网络是互连的&#xff0c;自治的计算机集合 互连:通过通信链路来进行互联互通 自治:没…...

C# Onnx Yolov8 Pose 姿态识别

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System…...

7.algorithm2e中while怎么使用

algorithm2e中while怎么使用 在 algorithm2e 宏包中&#xff0c;要使用 while 循环&#xff0c;您可以使用 \While 和 \EndWhile 命令来定义循环的开始和结束。以下是如何使用 while 循环的示例&#xff1a; \documentclass{article} \usepackage[linesnumbered,boxed]{algorit…...

Flask狼书笔记 | 08_个人博客(下)

文章目录 8 个人博客8.4 初始化博客8.5 使用Flask-Login管理用户认证8.6 CSRFProtect实现CSRF保护8.7 编写博客后台小结 8 个人博客 8.4 初始化博客 1、安全存储密码 密码不要以明文的形式直接存储在数据库中&#xff0c;以防被攻击者盗取、泄露。一般的做法是&#xff0c;不…...

机器学习第十课--提升树

一.Bagging与Boosting的区别 在上一章里我们学习了一个集成模型叫作随机森林&#xff0c;而且也了解到随机森林属于Bagging的成员。本节我们重点来学习一下另外一种集成模型叫作Boosting。首先回顾一下什么叫Bagging? 比如在随机森林里&#xff0c;针对于样本数据&#xff0c;…...

react scss.modules中使用iconfont

全局引入详见全局引入scss 全局的scss文件中引入iconfont.css use "../font/iconfont.css"; 然后就可以正常使用啦...

使用Jmeter+ant进行接口自动化测试(数据驱动)

最近在做接口测试&#xff0c;因为公司有使用jmeter做接口测试的相关培训资料&#xff0c;所以还是先选择使用jmeter来批量管理接口&#xff0c;进行自动化测试。话不多说&#xff0c;进入正题&#xff1a; 1.使用csv文件保存接口测试用例&#xff0c;方便后期对接口进行维护&…...

可视化图表组件之股票数据分析应用

股市是市场经济的必然产物&#xff0c;在一个国家的金融领域之中有着举足轻重的地位。在过去&#xff0c;人们对于市场走势的把握主要依赖于经验和直觉&#xff0c;往往容易受到主观因素的影响&#xff0c;导致决策上出现偏差。如今&#xff0c;通过数据可视化呈现&#xff0c;…...

STM32 ~ GPIO不同模式之间的区别与实现原理

GPIO全称General Purpose Input Output &#xff0c;即通用输入/输出。其实GPIO的本质就是芯片的一个引脚&#xff0c;通常在ARM中所有的I/O都是通用的。不过&#xff0c;由于每个开发板上都会设计不同的外围电路&#xff0c;这就造成了GPIO的功能可能有所不同。大部分GPIO都是…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...