项目中,遇到在嵌入式下展示html内容,并与之交互,Qt允许使用所谓的混合GUI创建应用程序——在这种GUI中,可以将本机部件与基于html的内容混合在一起。通过WebChannel和WebSockets提供交互,这种混合甚至支持这些本地部分和html端之间的交互。有三种方式:
使用webEngineView;
使用webView;
使用独立的Web浏览器(不会集成到应用程序中);
这三种方法以不同的方式进行,但都支持QML和HTML之间的通信。
确切的说,WebEngineView以一种方式完成,而WebView(就像网络浏览器一样)以另一种方式完成。WebEngineView和WebView是两码事。
webEngineView
WebEngineView是由Qt自己基于Chromium (Qt WebEngine)的web浏览器引擎提供的web视图。它是一个功能齐全的web浏览器,与Qt捆绑并集成在一起,这很好,但同时这意味着您需要将它与您的应用程序一起拖动,这是一个相当大的东西。
webView
WebView是一个web视图,但不同之处在于它使用平台的本地web浏览器(如果可用的话),因此它不需要将完整的web浏览器堆栈作为应用程序的一部分(WebEngineView就是这种情况),因此您的应用程序更轻量级。另一点是,有些平台根本不允许任何非系统的web浏览器,因此WebView是唯一可用的选项。
webEngineView 和 webView的区别
根据本文,WebEngineView和WebView的关键区别在于Qt如何与这些视图中的html内容通信。由于Chromium IPC功能,WebEngineView提供了最简单的方式-直接通过WebChannel,。而WebView(以及外部web浏览器)要求您首先为WebChannel建立一些传输。
本应用用到了 WebChannel 和 WebEngine 两个主要模块,所以要将下面这行添加到 qmake .pro 文件中:
QT += webchannel webengine
QML 服务端
在 QML 服务端,首先导入 Qt WebChannel 模块,以及 Qt WebEngine 模块:
import QtWebChannel 1.0
import QtWebEngine 1.5
然后创建一个想要发布到 HTML/JavaScript 客户端的对象:
QtObject {
id: myObject
// 注册方法 1
// 使用注册方法 2 时不需要此行代码
WebChannel.id: "foo" //这个 id 可以在 html 中使用
// 以下为 JavaScript 代码可以访问的信号、方法和属性
signal someSignal(string message);
function someMethod(message) {
console.log(message);
someSignal(message);
return "foobar";
}
property string hello: "world"
}
最后将该对象在 WebView 控件中发布到 HTML 客户端中:
WebEngineView {
anchors.fill: parent
url: "file:///C:/test.html"
webChannel: WebChannel {
id: webChannel
// 注册方法 1
registeredObjects: [myObject]
// 注册方法 2
//Component.onCompleted: {
// // "foo" 是该对象在 JavaScript 端的调用标识
// webChannel.registerObject("foo", myObject)
//}
}
}
main.qml文件如下
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 1.4
import QtWebView 1.1
import QtWebChannel 1.14
import QtWebEngine 1.10
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
QtObject {
id: myObject
// 注册方法 1
// 使用注册方法 2 时不需要此行代码
WebChannel.id: "foo" //这个 id 可以在 html 中使用
// 以下为 JavaScript 代码可以访问的信号、方法和属性
signal someSignal(string message);
function someMethod(message) {
console.log(message);
someSignal(message);
return "foobar";
}
property string hello: "world"
}
WebEngineView {
anchors.fill: parent
url: "qrc:/1.html"
webChannel: WebChannel {
id: webChannel
// 注册方法 1
registeredObjects: [myObject]
// 注册方法 2
//Component.onCompleted: {
// // "foo" 是该对象在 JavaScript 端的调用标识
// webChannel.registerObject("foo", myObject)
//}
}
}
}
html文件如下