javascript与qt交互通信

1,501 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

使用qt官方提供的QWebChannel,qwebchannel.js脚本,通过这个中间人的注入网页的qt对象,这样网页也能调用qt的函数

1. HTML网页发消息给qt的Chrome内核

class JsContext : public QObject{
  Q_OBJECT
  public:
    explicit JsContext(QObject * parent = nullptr);

  signals:
  void recvdMsg(const QString& msg);

  public:
  // 向页面发送消息
  void sendMsg(QWebEnginePage * page, const QString& msg);

public slots:
  // 接收到页面发送来的消息
  void onMsg(const QString& msg);
};

2. 初始化生成webChannel实例和jsContext(网页的qt对象)

m_jsContext = new JsContext(this);
m_webChannel = new QWebChannel(this);
m_webChannel->registerObject("context", m_jsContext); // 这里的"context"是HTML网页定义好的qt对象
m_webView->page()->setWebChannel(m_webChannel);
connect(m_jsContext, &JsContext::recvdMsg, this, [this](const QString& msg) {
    ui->statusBar->showMessage(QString("Received message:%1").arg(msg), 3000);
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webchannel测试</title>
</head>
<body>
    <input id="待发送消息" type="text" name="msgText" />
    <input type="button" value="发送消息到浏览器" onclick="onBtnSendMsg()" />
</body>
</html>
// 接收qt发送的消息
function recvMessage(msg){
    alert("接收到qt发送的消息:" + msg);
}

// 首先Qt端,上面的JsContext类已经声明了发送消息的方法sendMsg,其具体实现如下:
void JsContext::sendMsg(QWebEnginePage* page, const QString& msg){
    page->runJavaScript(QString("recvMessage('%1');").arg(msg));
}

3. qwebchannel.js脚本里导入方式是node的方式,得改成ES6导入方式

// required for use with nodejs
// if(typeof module ===' object){
//   module.exports = {
//     Qwebchannel: Qvebchannet
//   };
// }
export{
  QNebChannel
}

4. 对QWebChannel.js封装,其中channel.objects.context的“context”是qt代码预先注册起名的变量,onMsg,recvMessage也要预先在qt代码里注册的函数,而window.qt是qt浏览器的注入对象,接下来就可以通过约定注册函数进行交互通信

import QWebChannel from "qwebchannel.js"l;

class Qweb {
  constructor() {
    this.qtContext = undefined;
    this.init()
  }
  // 初始化
  init() {
    if (typeof window.qt !== 'undefined') {
      new QWebChannel(window.qt.webChannelTransport, function (channel) {
        this.qtContext = channel.objects.context;
      }
      );
    }
    else {
      console.log("window.qt对象获取失败!");
    }
  }

  // 向qt发送消息
  sendMessage(msg) {
    if (typeof qtContext == 'undefined') {
      console.log("qtContext对象获取失败!");
    }
    else {
      this.qtContext.onMsg(msg);
    }
  }

  // 控件控制函数
  onBtnSendMsg() {
    let cmd = document.getElementById("待发送消息").value;
    sendMessage(cmd);
  }
  
  // 接收qt发送的消息
  recvMessage(msg) {
    console.log("接收到Qt发送的消息:" + msg);
  }  
}

export default new Qweb()