QT5.7+使用QWebEngine+QWebChannel实现与HTML/JS双向通信

一种实现C++与HTML/JS双向通信的方案

前言

使用标记语言描述的界面是界面开发的一个趋势,基于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客户端之间进行无缝桥接,目前主要支持两种方式的桥接。

  1. 客户机可以是任何支持WebSockets的JavaScript runtime机器和应用,客户机可以是独立的应用或浏览器。也就是说QtWebChannel是基于WebSockets协议之上。
  2. 通过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();

官方示例

WebSocket

IPC


参考

QWebEngine 官方文档

QWebChannel 官方文档

说点什么

avatar
  Subscribe  
提醒
Optimized with PageSpeed Ninja