QT版本:5.6.2
void QWebChannel::registerObject(const QString &id, QObject *object)
3、C++通知HTML:通过信号将数据传给JS(例如signalToWeb), 故可发送信息。
4、HTML通知C++:直接调用槽函数(必须是槽函数)
5、如果有多处使用了QWebEngineView, 则多个QWebEngineView可以共享同一个QWebChannel,因此可以讲QWebChannel定义为一个全局的单例对象,并通过其注册多个Cpp对象。
void QWebEnginePage::setWebChannel(QWebChannel *channel);
m_webEngineView->page()->setWebChannel(m_webChannel);
6、重要:
1)触发发送信号(例如signalToWeb)的按钮不要放在设计师界面,因为UI模式的点击事件上发信号在该组件会出现无法响应的bug(5.7.1)。
2)在给HTML传数据之前,要确保其已经load加载完成了,因为load和setUrl都是异步的,所以需要使用信号-槽连接(在槽里面完成数据的传送)。
void QWebEngineView::load(const QUrl &url)
void QWebEngineView::setUrl(const QUrl &url)
connect(m_webEngineView, SIGNAL(loadFinished(bool)), this, SLOT(slotSendDataToH5(bool)));
核心类:QWebEngineView, QWebChannel
1、C++和HTML通过websocket通信,通过官方的 qwebchannel.js 实现。
2、C++和HTML共用一个对象并以此进行通信,即通过QWebChannel的registerObject函数。void QWebChannel::registerObject(const QString &id, QObject *object)
3、C++通知HTML:通过信号将数据传给JS(例如signalToWeb), 故可发送信息。
4、HTML通知C++:直接调用槽函数(必须是槽函数)
5、如果有多处使用了QWebEngineView, 则多个QWebEngineView可以共享同一个QWebChannel,因此可以讲QWebChannel定义为一个全局的单例对象,并通过其注册多个Cpp对象。
void QWebEnginePage::setWebChannel(QWebChannel *channel);
m_webEngineView->page()->setWebChannel(m_webChannel);
6、重要:
1)触发发送信号(例如signalToWeb)的按钮不要放在设计师界面,因为UI模式的点击事件上发信号在该组件会出现无法响应的bug(5.7.1)。
2)在给HTML传数据之前,要确保其已经load加载完成了,因为load和setUrl都是异步的,所以需要使用信号-槽连接(在槽里面完成数据的传送)。
void QWebEngineView::load(const QUrl &url)
void QWebEngineView::setUrl(const QUrl &url)
connect(m_webEngineView, SIGNAL(loadFinished(bool)), this, SLOT(slotSendDataToH5(bool)));
m_webEngineView->setUrl(QUrl("D:/testJsCallCpp/resources/index.html"));
C++代码:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWebEngineProfile>
#include <QWebEngineView>
#include <QWebChannel>
#include "document.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QJsonObject getUserInfoFromCpp();
private slots:
void slotSendDataToH5(bool ok);
private:
Ui::MainWindow *ui;
QWebEngineView *m_webEngineView;
QWebChannel *m_webChannel;
Document m_content;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
const QString HttpUserAgent_H5 = QString("Toon-pc/1.0.0 windows,android,iphone,ipad");
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_webEngineView = new QWebEngineView();
m_webEngineView->setContextMenuPolicy(Qt::NoContextMenu);
m_webChannel = new QWebChannel();
m_webChannel->registerObject(QStringLiteral("cppObject"), &m_content);
m_webEngineView->page()->setWebChannel(m_webChannel);
m_webEngineView->page()->profile()->setHttpUserAgent(HttpUserAgent_H5);
connect(m_webEngineView, SIGNAL(loadFinished(bool)), this, SLOT(slotSendDataToH5(bool)));
//m_webEngineView->setUrl(QUrl("https://www.baidu.com"));
m_webEngineView->setUrl(QUrl("D:/testJsCallCpp/resources/index.html"));
this->setCentralWidget(m_webEngineView);
}
MainWindow::~MainWindow()
{
delete ui;
}
QJsonObject MainWindow::getUserInfoFromCpp()
{
QJsonObject json;
json.insert("header", QStringLiteral("I am Qt!"));
return json;
}
void MainWindow::slotSendDataToH5(bool ok)
{
if (ok)
m_content.sendJsonToWeb(getUserInfoFromCpp());
else
qDebug()<<"load failed! ok="<<ok;
}
#ifndef DOCUMENT_H
#define DOCUMENT_H
#include <QDebug>
#include <QObject>
#include <QJsonObject>
Q_DECLARE_METATYPE(QJsonObject)
class Document : public QObject
{
Q_OBJECT
Q_PROPERTY(QJsonObject m_json READ getJson NOTIFY signalToWeb)
public:
explicit Document(QObject *parent = nullptr) : QObject(parent)
{
qRegisterMetaType<QJsonObject>("QJsonObject");
}
QJsonObject getJson() const
{
return m_json;
}
// cpp端直接通过对象调用
void sendJsonToWeb(const QJsonObject &json)
{
if (m_json != json)
{
m_json = json;
emit signalToWeb(json);
}
}
signals:
void receiveTextFromWeb(const QString &text);
// js端通过注册的对象ID调用
public slots:
// 必须为槽函数
void sendTextToCpp(const QString &text)
{
qDebug()<<"******from web*******text="<<text;
emit receiveTextFromWeb(text);
}
signals:
void signalToWeb(const QJsonObject &json);
private:
QJsonObject m_json;
};
#endif // DOCUMENT_H
HTML代码:
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="markdown.css">
<script src="marked.min.js"></script>
<script src="qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
<script>
'use strict';
window.onload = function() {
if (navigator.userAgent.indexOf('Toon-pc') !== -1) {
new QWebChannel(window.qt.webChannelTransport, function (channel) {
window.bridge = channel.objects.cppObject
// cpp通过signalToWeb信号给web传值:response
bridge.signalToWeb.connect(function (response) {
window.alert(response.header);
})
})
}
}
function fromWebToCpp()
{
// web调用cpp的 sendTextToCpp 方法,并带上参数
bridge.sendTextToCpp(JSON.stringify({
userId: 100
}))
}
</script>
<body>
<input id="add" type="button" value="传值给Cpp" class="button" οnclick="fromWebToCpp();"/>
</body>
</body>
</html>
运行效果: