Qt webengine 显示web页面、前后端通信以及下载详解

2023-11-20

概述

官方文档: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的功能分成下列模块:

  • Qt WebEngine Widgets 模块: 用于创建基于Widget的web应用.
  • Qt WebEngine 模块: 用于创建基于Qt Quick的web应用.
  • Qt WebEngine Core 模块: 与Chromium交互

环境安装

注意的是亮点,1、建议使用qt5.8之后的版本,网上说对webengine支持的好一点前面的版本可能会有bug。2、vs2015的编译器,网上说只能使用qt-msvc版本+vs2015编译器,我只试了这个版本,好使,其他的版本,没使用过不保证没问题。

vs2015

http://219.83.160.146:5476/%E8%BD%AF%E4%BB%B6%E5%8C%85/cn_visual_studio_community_2015_with_update_3_x86_x64_web_installer_8922965.exe

安装选项:1、command tools for visual c++2015  2、python tools for visual studio

win10sdk

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

Qt5.8

自己存的:http://219.83.160.146:5476/%E8%BD%AF%E4%BB%B6%E5%8C%85/qt-opensource-windows-x86-msvc2015_64-5.8.0.exe

官网的:Index of /archive/qt

构建套件的时候选择vs的编译器就可以了,debug选择win10sdk中的调试器

简单页面显示

打开Qt新建一个项目,在.pro文件里面添加QT += webenginewidgets之后跟着下面这个链接走就行了

QT webengine 例子_small house-CSDN博客 很简单,就不多叙述了,网上的资料也很多。

我在使用过程中经常会遇到new一个对象但是提示链接错误的情况,其实代码是对的,可能是Qt ide的原因,可以试试把编译的目录全部删了,之后重新编译,有可能会修复哦。

与前端js交互

这一块很重要,也是我研究的比较多的地方,先给出两篇对我研究过程最有用的文档。

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的使用方法大家可以借鉴。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt webengine 显示web页面、前后端通信以及下载详解 的相关文章

  • 如何在 QT 中绘制点?

    我正在用 QT 用 C 编写一个应用程序 其中有 n 个点并计算它的凸包 然而 一旦计算出来 我不知道如何绘制点并绘制船体的边界 制作菜单按钮等很简单 但我不确定我是否知道执行此操作的工具 你怎么做到这一点 图形视图 addEllipse
  • Qt5和QML:如何使用WebEngine Quick Nano浏览器自动输入用户名和密码

    我正在使用编写一个小应用程序Qt and QML使用 Qt 文档中的示例WebEngine Quick Nano 浏览器 https doc snapshots qt io qt5 5 9 qtwebengine webengine qui
  • 仅在内部/外部抚摸路径?

    Given a QPainterPath http qt project org doc qt 4 8 qpainterpath html如何仅在路径的内侧或外侧边缘 或非闭合路径的左侧或右侧 描边路径 QPainter strokePat
  • 用 C++/Qt 编写的程序中的 RTF / doc / docx 文本提取

    我正在写一些程序Qt https en wikipedia org wiki Qt 28software 29 C 我需要从中读取文本微软Word https en wikipedia org wiki Microsoft Word RTF
  • QStyledItemDelegate 绘制自定义小部件失败

    在我的一个项目中 我使用的是QTableWidget为了显示一些复杂的计算结果 为了提高表格的可读性 我需要在单个表格单元格内显示两个对齐的值 后来我想通过使用颜色或箭头等来进一步自定义小部件 为此我源自QStyledItemDelegat
  • QT:删除QGridLayout中QLabel之间的空格

    我将一些具有不同颜色的 QLabels 添加到 QGridLayout 作为 QWidget 的布局 现在我在每个 Qlabel 与下一个 Qlabel 之间有一个间距 我想将其删除 我尝试将标签的边距设置为 0 将 GridLayout
  • 将 jstring 转换为 QString

    我正在调用一个返回字符串的 Java 函数 QAndroidJniObject obj QAndroidJniObject callStaticObjectMethod
  • 在 Qt 中使用多个不同的流读取同一文件

    使用 Qt 是否可以使用多个流读取文件以同时访问其中的不同数据部分 请注意 Qt 中的流 QTextStream QDataStream 不处理底层设备中的位置 流类只是一个包装器 用于更轻松地解析设备 QFile 实例 内的二进制数据 因
  • PyQt4 QPalette 不工作

    btn QtGui QPushButton Button self palettes btn palette palettes setColor btn backgroundRole QtCore Qt green btn setPalet
  • 如何doxygen注释Qt属性?

    我想将 Doxygen 注释附加到我的 Q PROPERTY 例如 song h class Song public QObject Q OBJECT private Q PROPERTY QString title READ title
  • 如何将自定义 Qt 类型与 QML 信号一起使用?

    我在 Qt 5 2 qml 应用程序中创建了一个自定义类型 class Setting public QObject Q OBJECT Q PROPERTY QString key READ key WRITE setKey Q PROPE
  • 连接到 QNetworkReply::error 信号

    我正在使用 Qt5 的新连接语法 QNetworkReply 有一个名为error http qt project org doc qt 5 0 qtnetwork qnetworkreply html error 2还有一个函数叫做err
  • Qt QML 数据模型似乎不适用于 C++

    我一直在使用中的示例http doc qt digia com 4 7 qdeclarativemodels html http doc qt digia com 4 7 qdeclarativemodels html这是 QML 声明性数
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • 即使我在单独的线程中运行,QT GUI 也会冻结

    我有一个小型聊天应用程序 其中使用 SQLite 数据库来存储所有对话 我注意到该应用程序随机冻结 然后我必须最小化和最大化它才能使其再次工作 我认为问题可能是 SQLite 选择 插入导致 gui 冻结 我决定尝试将所有 SQLite 方
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • Qt 相当于 .NET 数据绑定吗?

    Qt 中是否有相当于 NET 数据绑定的功能 我想使用引用数据库中特定实体的 QString 填充一些组合框和其他小部件 但是 如果我可以将数据绑定到这些字符串 而不是基于新的组合框选择再次查询数据库 或者基于构建我自己的将使用 QStri
  • Qt - 如何使用 QNetworkAccessmanager 获取响应文本

    这是我的代码 Widget Widget manager new QNetworkAccessManager this connect manager SIGNAL finished QNetworkReply this SLOT repl
  • 使用 QWT 构建时出错

    我收到一个错误 undefined reference to QwtPlot QwtPlot QWidget 当我尝试构建我的项目时 即使设置中一切看起来都很好 在我的 CmakeLists txt 中我有 include director
  • QML MouseArea 将事件传播到按钮

    我正在开发一个应用程序 其菜单类似于 Android 版 Gmail 收件箱应用程序菜单 基本上 当您按下按钮打开菜单时 它就会滑入视图 用户可以将其滑开或按菜单上的按钮 对于滑动我使用了代码SwipeArea from kovrov ht

随机推荐

  • android studio agpbi error,Android Studio 3.1.1 打Jar包出现AGPBI异常解决

    今天 写好Demo兴致勃勃准备打个Jar包在Unity中测试下 不料 突然出现AGPBI这个异常 日志如下 AGPBI kind error text Program type already present android support
  • Android Recyclerview焦点变化问题导致下拉刷新视觉卡顿

    如题 最近做项目时偶然发现了一个Recyclerview嵌套Recycleview的问题 业务模块是订单列表 涉及到一个订单包含多个子订单的情况 所以考虑使用嵌套来展示页面 这一切都是正常的 没有任何问题 然而 随着业务的展开需要查看详情单
  • 自己写的PLC编程软件,和FANUC PMC功能基本保持一致

    自己写的PLC编程软件 和FANUC PMC功能基本保持一致 下载地址 免积分 链接 pan baidu com s 162 GcF7wh SNT3McATPPmg 提取码 1234 https download csdn net down
  • 基于ShuffleNetv2-YOLOv4模型的目标检测

    目录 1 引言 摘要 1 1 说明 1 2替换完成的工程请参考gitee 2 网络结构基础 2 1YOLOv3 2 1 YOLOv4算法 2 3 ShuffleNetv2 2 4 替换后的网络结构 3 实验结果 3 1实验环境配置及数据集介
  • 时间复杂度+常见复杂度解释

    前言 算法的效率 虽然计算机能快速的完成运算处理 但实际上 它也需要根据输入数据的大小和算法效率来消耗一定的处理器资源 要想编写出能高效运行的程序 我们就需要考虑到算法的效率 算法的效率主要由以下两个复杂度来评估 时间复杂度 评估执行程序所
  • Vue long精度丢失问题

    原因 vue前端对long类型的精度无法接收 javascript 的 Number 类型最大长度是17位 mysql 使用bigint 类型长度是20位 前端解决方法 在全局的网络请求 用了一个处理数据的插件 来转换 后端解决的方法 Co
  • 网络安全不可忽视!企业如何做好网络安全。

    随着互联网的高速发展 其面临的安全隐患也暴露无疑 比如网络攻击 黑客入侵等 都会严重影响到网络业务的运行 为此很多企业都绞尽脑汁寻找抵御各类网络安全隐患 国家也出台了相关的等保方案让企业能够免于后顾之忧 下面我们来说说目前网络安全的具体内容
  • android音视频!BAT大厂面试基础题集合,不吃透都对不起自己

    前言 现在已经进入招聘季节 本篇文章旨在分享知名互联网企业面试官面试方法和心得 希望通过本文的阅读能给程序员带来不一样的面试体验和感受 放松面试心态 积极备战 找到正确的学习路线 一 架构师专题 想要掌握复杂的技术 必须要理解其原理和架构
  • ROS学习笔记(二)文件系统

    ROS学习笔记 二 文件系统 开篇 ROS的文件系统结构 要学会建立一个ROS工程 首先要认识一个ROS工程 了解它们的组织架构 从根本上熟悉ROS项目的组织形式 了解各个文件的功能和作用 才能正确的进行开发和编程 本章的主要内容有 介绍c
  • 就现在!为元宇宙和Web3对互联网的改造做准备!

    欢迎来到Hubbleverse 关注我们 关注宇宙新鲜事 预计阅读时长 8分钟 本文仅代表作者个人观点 不代表平台意见 不构成投资建议 如今 互联网是各种不同的网站 应用程序和平台的集合 由于彼此分离 它们缺乏互操作性和数据可移植性 因此
  • ant design vue中menu组件递归渲染报错解决

    ant design vue中menu组件递归渲染报错 开始递归组件后打开页面后报错如下 解决如下 使 单 件 式递归 成菜单 Before v2 0 因组件内部会动态更改a sub menu的属性 如果拆分单文件 无法将属性挂载到a su
  • BI的需求调研的方法分类

    今天看到一篇文章 里面提到需求调研的几种思路 觉得分类有些道理 结合项目写一下 这种方法论在指导实践和体现专业两个方面都很实用 1 现有报表 这个是最常用的 使用这种方法注意区别报表目的 紧急度 和数据是否适合在BI实现 细节度 为什么以前
  • Oracle统计多张表的Count数的和

    需求描述 Table1 job1 job1 id name status other column 1 file1 process 2 file2 failed 3 file3 success Table2 job2 job2 id nam
  • 03:MYSQL----DQL,聚合函数

    目录 1 介绍 2 语法 3 聚合函数 4 DOL 语句练习 5 SQL执行顺序 1 介绍 数据查询语言 用来查询数据库中表的记录 2 语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表
  • 手写 git hooks 脚本

    我们的 Git 仓库中包含了编译后的代码 所以每次修改了源码 都需要运行一下编译命令 然后把源码和编译后的代码一起提交到 Git 仓库 这个流程没什么问题 但是 人脑不是电脑 总会有疏忽的时候 经常会出现这样一种情况 修改了源码 却忘记了运
  • sql判断字段是否为null,是否为空串

    问题现象 今天在项目中思考了一个问题 如何在sql中判断一个字段是否为 null值 是否为 空串 呢 问题分析 需要注意的是 null值 和 空串 并不是同一个概念 null值 就是这个字段没有赋值 也就是java中常说的 null 而 空
  • 权重实现随机抽奖

    一般抽奖是怎么实现的 在实习期间学会了一种通用的写法 在这里记录一下 最近在学Golang语法基础 这里就用Golang来写 package main import fmt time math rand func main r rand N
  • 模态对话框与非模态对话的几种销毁方法与区别

    前几天发现自己的程序中使用非模态对话框 Debug版本有警告提示如下 Warning calling DestroyWindow in CWnd CWnd OnDestroy or PostNcDestroy in derived clas
  • 关于高并发与多线程中的线程池

    关于高并发与多线程中的线程池 定义 线程是稀缺资源 它的创建与销毁是一个相对偏重且耗资源的操作 而Java线程依赖于内核线程 创建线程需要进行操作系统状态切换 为避免资源过度消耗需要设法重用线程执行多个任务 线程池就是一个线程缓存 负责对线
  • Qt webengine 显示web页面、前后端通信以及下载详解

    概述 官方文档 https doc qt io archives qt 5 11 qtwebengine overview html 翻译文档 Qt5 9 WebEngine 概述 一花一世界 一叶一乾坤 博客园 从Qt5 5开始 Qt W