前言
很早以前就听说过Qt也能显示网页,一直没有机会真正研究应用起来,刚好最近项目中使用到了QWebEngine内嵌浏览器打开第三方的网站,使用的Qt版本为5.15,踩了不少的坑,这里做个总结。
QWebEngine架构
- Qt WebEngine Widgets---用于创建基于widget的web应用程序
- Qt WebEngine Module---用于创建基于Qt Quick的web应用程序
- Qt WebEngine Core---Qt WebEngine Core与Chromium相互作用
- Qt WebEngine Process---页面渲染和JavaScript执行进程
Qt WebEngine Widgets
Web引擎视图是Qt WebEngine模块的主要小部件组件。它可用于各种应用程序来加载网页内容。在视图中,Web引擎页面包含一个主框架,负责Web内容、导航链接的历史和操作。视图和页面非常相似,因为它们提供了一组共同的功能。
所有页面都属于包含共享设置、脚本和cookie的Web引擎配置文件。配置文件可用于将页面相互隔离。一个典型的用例是私人浏览模式的专用配置文件,其中不会永久保存任何信息。
Qt WebEngine Module
Qt WebEngine QML实现包含与Qt WebEngine Widgets实现相同的元素,只是没有单独访问的Web引擎页面。支持的页面功能已集成到Web引擎视图中。
Qt WebEngine Core
Qt WebEngine核心基于Chromium Project。Chromium提供自己的网络和渲染引擎,并与其依赖模块紧密合作开发。
Qt WebEngine Process
Qt WebEngine进程是一个单独的可执行文件,用于渲染网页和执行JavaScript。这缓解了安全问题,并隔离了由特定内容引起的崩溃。我们日常使用的浏览器也是基于多进程实现,一个tab对应一个进程。
上面的框架说明来自Qt官方文档,QWebEngine有QWidget和QML两种加载网页的方式,其中都是调用封装了谷歌Chromium内核的QWebEngineCore模块,可根据项目情况选择widget或者qml框架。本人现在用qml比较多,后续介绍的内容也主要是针对qml。
WebEngineView基本用法
int main(int argc, char *argv[])
{
QCoreApplication::setOrganizationName("QtExamples");
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QtWebEngine::initialize();
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
import QtQuick 2.0
import QtQuick.Window 2.0
import QtWebEngine 1.0
Window {
width: 1024
height: 750
visible: true
WebEngineView {
anchors.fill: parent
url: "https://www.qt.io"
}
}
qml中使用需在Qt Quick Engine前执行QtWebEngine::initialize();,该初始化操作是为了确保OpenGL上下文可以在GUI和渲染进程之间共享,如果用的是widget,是不需要这一步。
打包发布
Win下打包用windeployqt工具正常打包即可,QML项目打包出来包含以下项目,缺一个都不能正常使用
Mac下打包同样的用macdeployqt打包,但是打包出来的QWebEngineCore库是不完整的,需手动拷复制,这个应该是Qt5.15macdeployqt的bug
Mac下使用QWebEngine,QWebEngineCore库必须是放在调用的进程的上一级目录的Frameworks,如果你的项目是多进程,子进程也有用QWebEngine,如果想和主进程共用一份库,那样会有问题,子进程会报错icu_util.cc(199)] Couldn't mmap icu data file,这个问题在Qt6.4上验证是解决了。
结语
本篇文章是针对QWebEngine应用的一个综述,后面针对项目中运用到的具体内容做介绍,主要有cookies的存储应用、注入javasript、基于QWebChannel实现网页与C++通信等内容。