QT C++ QWebEngine与Web JS之间通信

Qt 与 Web 通信指南(QWebEngineView + QWebChannel)

概览

  • 目标:让网页 JavaScript 与 Qt 客户端进行双向通信(调用本地方法、通知 UI)。
  • 技术栈:Qt WebEngineWidgets + Qt WebChannel + JavaScript qwebchannel.js
  • 适用场景:在 QWebEngineView 内嵌外部或内部网页,并需要与桌面端交互。

通信模型

  • Qt 暴露一个 QObject(如 WebBridge),注册到 QWebChannel
  • Web 端通过 qwebchannel.js 获得该对象(例如 bridge),直接调用其 slot 方法。
  • Qt 端通过 signals 向 UI 或其他模块转发事件,或主动调用 evaluateJavaScript 与 Web 交互。

快速集成步骤

  1. 引入依赖并链接:

    • CMake:

      cmake 复制代码
      find_package(Qt6 REQUIRED COMPONENTS WebEngineWidgets WebChannel)
      target_link_libraries(QuantClient PRIVATE Qt6::WebEngineWidgets Qt6::WebChannel)
  2. 实现桥对象(Qt → Web 暴露):

    • src/gui/web/WebBridge.h / src/gui/web/WebBridge.cpp
    • 暴露 slot,在需要处 emit 信号给 UI 层。
  3. QWebEngineView 完成加载前注册通道:

    • webView->page()->setWebChannel(channel);
  4. Web 端加载 qwebchannel.js 并初始化通道,获取 bridge 对象进行调用。

Qt 侧代码示例

cpp 复制代码
// StrategyPerformanceDialog.cpp(片段)
QWebChannel* channel = new QWebChannel(this);
WebBridge* bridge = new WebBridge(this);
channel->registerObject(QStringLiteral("bridge"), bridge);
webView->page()->setWebChannel(channel);
QObject::connect(bridge, &WebBridge::openStrategyDetailRequested, this, &StrategyPerformanceDialog::onStrategyDetailRequested);
cpp 复制代码
// WebBridge.h(片段)
class WebBridge : public QObject {
    Q_OBJECT
public:
    explicit WebBridge(QObject *parent = nullptr);
public slots:
    void refreshStrategyData();
    void openStrategyDetail(const QString &strategyId);
signals:
    void openStrategyDetailRequested(const QString &strategyId);
};
cpp 复制代码
// WebBridge.cpp(片段)
void WebBridge::openStrategyDetail(const QString &strategyId) {
    emit openStrategyDetailRequested(strategyId);
}

Web 侧代码示例

页面可改(直接在 HTML 中)

html 复制代码
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script>
  new QWebChannel(qt.webChannelTransport, function(channel) {
    const bridge = channel.objects.bridge;
    bridge.refreshStrategyData();
    bridge.openStrategyDetail("strategy_123");
  });
</script>

页面不可改(Qt 侧注入)

cpp 复制代码
// 加载完成后动态注入脚本
connect(webView, &QWebEngineView::loadFinished, this, [webView](bool){
    webView->page()->runJavaScript(R"((function(){
      var s=document.createElement('script');
      s.src='qrc:///qtwebchannel/qwebchannel.js';
      s.onload=function(){
        new QWebChannel(qt.webChannelTransport,function(c){
          window.bridge=c.objects.bridge;
        });
      };
      document.head.appendChild(s);
    })();)"
    );
});

预注入(更稳,文档创建阶段)

cpp 复制代码
QWebEngineScript script;
script.setName(QStringLiteral("qwebchannel-loader"));
script.setInjectionPoint(QWebEngineScript::DocumentCreation);
script.setWorldId(QWebEngineScript::MainWorld);
script.setRunsOnSubFrames(true);
script.setSourceCode(QStringLiteral(
  "(function(){var s=document.createElement('script');" 
  "s.src='qrc:///qtwebchannel/qwebchannel.js';" 
  "s.onload=function(){new QWebChannel(qt.webChannelTransport,function(c){window.bridge=c.objects.bridge;});};" 
  "document.head.appendChild(s);})();"
));
webView->page()->scripts().insert(script);

常见问题与排错

  • 链接错误:Undefined symbols for architecture arm64 → 未将 WebBridge.cpp 加入构建或未链接 Qt6::WebChannel
  • 头文件找不到:'config/AppConfig.h' file not found#include 相对路径错误,从 src/gui/mainwindowsrc/gui/config 需用 ../config/AppConfig.h
  • qwebchannel.js 加载失败:确保使用 qrc:///qtwebchannel/qwebchannel.js,并已链接 Qt6::WebChannel
  • JS 不生效:确认已调用 webView->page()->setWebChannel(channel),且对象名与 JS 一致(如 bridge)。

安全与最佳实践

  • 只暴露必要的 slot,在 Qt 侧校验参数与权限。
  • 对外部页面建议使用注入方式并限制可用接口。
  • 使用明确的对象名与命名空间,避免冲突。

扩展能力

  • Qt → Web 主动调用:webView->page()->runJavaScript("doSomething()")
  • Web → Qt 回调返回值:QWebEnginePage::runJavaScript 支持回调函数拿到执行结果。
相关推荐
会叫的恐龙16 小时前
C++ 核心知识点汇总(第11日)(排序算法)
c++·算法·排序算法
符哥200817 小时前
C++ 适合初学者的学习笔记整理
c++·笔记·学习
iDao技术魔方17 小时前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
javascript·vue.js·ecmascript
历程里程碑17 小时前
普通数组-----除了自身以外数组的乘积
大数据·javascript·python·算法·elasticsearch·搜索引擎·flask
摸鱼的春哥17 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响17 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
星火开发设计17 小时前
this 指针:指向对象自身的隐含指针
开发语言·数据结构·c++·学习·指针·知识
梵刹古音17 小时前
【C++】构造函数
开发语言·c++
Amumu1213817 小时前
Vue3 Composition API(一)
开发语言·javascript·ecmascript
草莓熊Lotso17 小时前
Qt 主窗口核心组件实战:菜单栏、工具栏、状态栏、浮动窗口全攻略
运维·开发语言·人工智能·python·qt·ui