QT5.7+使用QWebEngine+QWebChannel实现与HTML/JS双向通信
一种实现C++与HTML/JS双向通信的方案
Contents
前言
使用标记语言描述的界面是界面开发的一个趋势,基于html的B/S架构在开发效率、可移植性、运维、更新上十分有优势,同时采用这种方案也是为了未来hybird应用开发做准备。本文将简单介绍使用QWebChannel实现与html/js双向通信的方法。
简介
- Qt WebEngine
Qt开发团队在5.6版本以后已经停止对Webkit的支持,取而代之的是基于chromium内核开发的QWebEngine模块。该模块不但集成了跨平台的API,还可以混合Qt界面或者OpenGL。因此对于需要Web能力的项目,建议在Qt5.7版本以上基于QWebEngine进行开发
- Qt WebChannel
QWebChannel模块在QWebEngine的模块下可以开箱即用。它支持服务器和客户端(HTML/JavaScript或QML)应用程序之间的点对点通信。另外,它可以在支持WebSockets的所有浏览器上工作,使QWebChannel客户端可以在任何JavaScript环境(包括QML)中运行。
该模块提供了一个JavaScript库,用于实现C++/QML应用程序与HTML/JavaScript或QML客户端无缝集成。客户端必须使用JavaScript库来访问主机应用发布的QObject
功能与示例
使用Qt WebEngine访问HTML/JS
- 在Qt程序中加载web页面
QWebEngineView * view = new QWebEngineView(parent); view - > load( QUrl( “http://yourhtml/”)); view - > show();
- 在Qt程序中调用js
使用QWebEnginePage类的成员函数runJavaScript
view->page()->runJavaScript("showAlert()");
使用Qt WebChannel实现双向通信
通过QtWebChannel能够实现C++/QML和HTML/javascript客户端之间进行无缝桥接,目前主要支持两种方式的桥接。
- 客户机可以是任何支持WebSockets的JavaScript runtime机器和应用,客户机可以是独立的应用或浏览器。也就是说QtWebChannel是基于WebSockets协议之上。
- 通过IPC的方式实现C++/QML和HTML/javascript客户端之间进行通信。在QT应用内嵌入HTML或JS页面的情况下使用基于IPC的WebChannel通信。
第二种方式效率更高效,但高级浏览器功能需要额外的开发(如代理、mp4播放、证书管理、cookies等 ),很多高级功能的api只有高版本的qt才能提供。请根据具体需求选择一种方式桥接
在Qt程序中初始化socket
//listen localhost:port
QWebSocketServer server(QStringLiteral("WebSocket Setup !"), QWebSocketServer::NonSecureMode);
if (!server.listen(QHostAddress::LocalHost, port)) {
qFatal("Failed to open web socket server.");
return 1;
}
// wrap WebSocket clients in QWebChannelAbstractTransport objects
WebSocketClientWrapper clientWrapper(&server);
在Qt程序中初始化QWebChannel
1. 使用WebSocket
QWebChannel channel;
QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected,&channel, &QWebChannel::connectTo);
channel.registerObjects("content", &m_content);
2. 使用IPC
QWebChannel *channel = new QWebChannel(this);
channel->registerObject("content", &m_content);
view->page()->setWebChannel(channel);
在Qt程序中通过webchannel调用js方法
m_content.setSendTextText(ui->lineEdit->text());
在网页中初始化webchannel
1. 使用WebSocket
if (location.search != "")
var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);
else
var baseUrl = "ws://localhost:port";
var socket = new WebSocket(baseUrl);
socket.onclose = function()
{
console.error("web channel closed");
};
socket.onerror = function(error)
{
console.error("web channel error: " + error);
};
socket.onopen = function()
{
new QWebChannel(socket, function(channel
{
content =channel.objects.content;
}
};
2. 使用IPC
new QWebChannel(qt.webChannelTransport,function(channel){
var content=channel.objects.content;
}
在网页中调用Qt程序方法
content.qtfunction();
说点什么