Qt5.15 QML WebView实现Native函数暴露与JS-Native通信
实现Qt WebEngineView与网页JS的Native函数调用(类似Java addJavascriptInterface)
需求说明
使用Qt5.15.3结合QML开发,需要实现类似Java WebView中addJavascriptInterface的功能:将Native端的函数暴露给网页,让网页中的JavaScript可以直接调用Native方法完成交互。
Java实现参考示例
WebView初始化代码
// In your WebView setup code WebView webView = findViewById(R.id.webView); NativeInterface nativeInterface = new NativeInterface(); webView.addJavascriptInterface(nativeInterface, "NativeInterface");
NativeInterface类
public class NativeInterface { @JavascriptInterface public void CANBUS_Write(String id,String[] data) { // Call the native CANBUS_Write function here with the provided data } }
网页端调用代码
function CANBUS_Write(id, data) { window.NativeInterface.CANBUS_Write(id, data); }
本人尝试的Qt代码
ServerSideHandler.h
#ifndef SERVERSIDEHANDLER_H #define SERVERSIDEHANDLER_H #include <QObject> #include <QStringList> class ServerSideHandler : public QObject { Q_OBJECT public: explicit ServerSideHandler(QObject *parent = nullptr); public slots: void CANBUS_Write(const QString &ID, const QStringList &data); }; #endif // SERVERSIDEHANDLER_H
ServerSideHandler.cpp
#include "serversidehandler.h" #include <QDebug> ServerSideHandler::ServerSideHandler(QObject *parent) : QObject(parent) { qDebug() <<"Init"; } void ServerSideHandler::CANBUS_Write(const QString &ID, const QStringList &data) { QStringList sBuffer; for (const QString &item : data) { sBuffer.append(item); } qDebug() << "CANBUS_Write ID" << ID << ", data =" << sBuffer.join(' '); }
main.cpp
qmlRegisterType<ServerSideHandler>("ServerSideHandler", 1, 0, "ServerSideHandler");
main.qml
ServerSideHandler{ id :server } WebView { id:webView anchors.fill: parent url: "http://192.168.120.56:8888/test" Component.onCompleted: { channel.registerObject("NativeInterface",server); } WebChannel{ id: channel } }
正确实现方案
1. 项目配置修正
首先确保.pro文件中添加必要的Qt模块支持:
QT += core gui qml quick webengine webchannel SOURCES += \ main.cpp \ ServerSideHandler.cpp HEADERS += \ ServerSideHandler.h RESOURCES += qml.qrc
2. QML代码修正(替换为WebEngineView)
Qt的WebView(QtWebView模块)封装原生系统WebView,不支持WebChannel;需使用WebEngineView(QtWebEngine模块)实现通信:
import QtQuick 2.15 import QtQuick.Window 2.15 import QtWebEngine 1.15 import ServerSideHandler 1.0 Window { width: 800 height: 600 visible: true title: qsTr("WebChannel Demo") ServerSideHandler { id: server } WebEngineView { id: webEngineView anchors.fill: parent url: "http://192.168.120.56:8888/test" // 将WebChannel与WebEngineView绑定 webChannel: channel WebChannel { id: channel Component.onCompleted: { // 注册Native对象到WebChannel,名称为"NativeInterface" registerObject("NativeInterface", server) } } } }
3. 网页端代码适配
网页需要引入Qt官方提供的qwebchannel.js文件(可从Qt安装目录Qt5.15.3/5.15.3/[编译器]/lib/QtWebChannel.5.15.3/resources/qwebchannel.js获取),并通过WebChannel建立连接:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test Page</title> <!-- 引入qwebchannel.js,确保路径正确 --> <script src="qwebchannel.js"></script> </head> <body> <button onclick="testCallNative()">调用Native CANBUS函数</button> <script> let nativeInterface; // 初始化WebChannel连接 new QWebChannel(qt.webChannelTransport, function(channel) { // 获取Native端注册的对象 nativeInterface = channel.objects.NativeInterface; }); function CANBUS_Write(id, data) { if (nativeInterface) { nativeInterface.CANBUS_Write(id, data); } } // 测试调用函数 function testCallNative() { CANBUS_Write("0x123", ["0x01", "0x02", "0x03"]); } </script> </body> </html>
关键注意事项
qwebchannel.js必须正确加载:可放置在网页同目录,或打包到Qt资源文件中通过资源路径访问。- 参数类型兼容:Qt的
QString对应JS字符串,QStringList对应JS数组,基本类型会自动完成转换。 - 确保WebChannel与WebEngineView正确绑定:必须通过
webChannel属性关联,否则无法建立通信。
内容的提问来源于stack exchange,提问作者jason yu
相关产品推荐
相关产品推荐

