参考网址:http://blog.csdn.net/liuyez123/article/details/50509788
  ZC: 该文章里面的:
  “
    <ahref="javascript:document.getElementByIdx_x("myLabel").setText("通过JavaScript访问Qt对象");"mce_href="javascript:document.getElementByIdx_x("myLabel").setText("通过JavaScript访问Qt对象");">点击访问Qt对象</a>
  ”
    貌似使用的机制是 "WebKik & QWebPluginFactory",貌似在WebEngine中暂时(至20160926为止)还没有...

https://www.google.com.hk 搜索 “getElementByIdx_x("myLabel").setText QT”得到 仅有的4个结果:
  http://www.programgo.com/article/54841979099/
  http://blog.hehehehehe.cn/a/10652.htm
  http://www.360doc.com/content/16/0405/18/13792507_548095953.shtml
  http://blog.inet198.cn/?liuyez123/article/details/50509788

1、我的代码:

  1.1、pro

QT       += core gui    \
webenginewidgets webchannel
CONFIG += c++11 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = QWebEngine_JiaoHu
TEMPLATE = app SOURCES += main.cpp\
mainwindow.cpp \
document.cpp \
previewpage.cpp HEADERS += mainwindow.h \
document.h \
previewpage.h FORMS += mainwindow.ui

  1.2、main.cpp ==> 默认

  1.3、mainwindow.h 和 mainwindow.cpp

    1.3.1、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow>
#include "document.h" namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow(); private slots:
void on_pushButton_clicked(); private:
Ui::MainWindow *ui; private:
bool isModified() const;
Document m_content;
}; #endif // MAINWINDOW_H

    1.3.2、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h" #include "previewpage.h"
#include <QWebChannel> MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this); // *** PreviewPage *page = new PreviewPage(this);
ui->preview->setPage(page);
m_content.setUi(ui); QWebChannel *channel = new QWebChannel(this);
channel->registerObject(QStringLiteral("content"), &m_content);
page->setWebChannel(channel); //ui->preview->setUrl(QUrl("qrc:/index.html"));
ui->preview->setUrl(QUrl::fromUserInput("F:/ZZ_Qt5/QWebEngine_JiaoHu/html/index.html")); ui->editor->setPlainText("hello...\n");
} MainWindow::~MainWindow()
{
delete ui;
} bool MainWindow::isModified() const
{
return ui->editor->document()->isModified();
} void MainWindow::on_pushButton_clicked()
{
m_content.setSendTextText(ui->lineEdit->text());
}

  1.4、previewpage.h 和 previewpage.cpp ==> 用于在 打开网页的时候,做一下处理(相当于过滤层) :如果网址 如何要求就通过(打开网页),如果 网址不符合要求 就拒绝(不打开网页)

    1.4.1、previewpage.h

#ifndef PREVIEWPAGE_H
#define PREVIEWPAGE_H #include <QWebEnginePage> class PreviewPage : public QWebEnginePage
{
Q_OBJECT
public:
explicit PreviewPage(QObject *parent = nullptr) : QWebEnginePage(parent) {} protected:
bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame);
}; #endif // PREVIEWPAGE_H

    1.4.2、previewpage.cpp

#include "previewpage.h"

#include <QDesktopServices>

bool PreviewPage::acceptNavigationRequest(const QUrl &url,
QWebEnginePage::NavigationType /*type*/,
bool /*isMainFrame*/)
{
// Only allow qrc:/index.html.
if (url.scheme() == QString("qrc"))
return true;
//QDesktopServices::openUrl(url); // ZC: 这一句代码,会打开 本地的默认浏览器,显示相关的网页
//return false; // ZC: 返回 false的话,就不打开 相应的网页
return true; // ZC: 返回 false的话,就打开 相应的网页
}

  1.5、document.h 和 document.cpp ==> 这个是 JS和C++交互的类

    1.5.1、document.h

#ifndef DOCUMENT_H
#define DOCUMENT_H #include <QObject>
#include <QString>
#include "ui_mainwindow.h" namespace Ui {
class MainWidget;
} class Document : public QObject
{
Q_OBJECT
Q_PROPERTY(QString text MEMBER s_text NOTIFY sendText) public:
explicit Document(QObject *parent = nullptr) : QObject(parent) {} void setSendTextText(const QString &text);
void setUi(Ui::MainWindow *ui); public slots:
void receiveText(const QString &r_text); signals:
void sendText(const QString &text); private:
void displayMessage(const QString &message);
QString s_text;
QString recieve_text;
Ui::MainWindow *mainUi;
}; #endif // DOCUMENT_H

    1.5.2、document.cpp

#include "document.h"
#include <QDebug> void Document::setSendTextText(const QString &text)
{
s_text = text;
qDebug() << "Document::setSendTextText" << s_text;
emit sendText(s_text);
} void Document::displayMessage(const QString &message)
{
mainUi->editor->appendPlainText(message);
} /*!
This slot is invoked from the HTML client side and the text displayed on the server side.
*/
void Document::receiveText(const QString &r_text)
{
displayMessage(QObject::tr("Received message: %1").arg(r_text));
} void Document::setUi(Ui::MainWindow *ui)
{
mainUi = ui;
}

  1.6、网页 源码

    1.6.1、index.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="./qwebchannel.js"></script>
<script type="text/javascript">
//BEGIN SETUP
function output(message)
{
var output = document.getElementById("output");
output.innerHTML = output.innerHTML + message + "\n";
}
window.onload = function() { output("setting up QWebChannel.");
new QWebChannel(qt.webChannelTransport, function(channel) {
// make dialog object accessible globally
var content = channel.objects.content; document.getElementById("send").onclick = function() {
var input = document.getElementById("input");
var text = input.value;
if (!text) {
return;
} output("Sent message: " + text);
input.value = "";
content.receiveText(text);
} content.sendText.connect(function(message) {
output("Received message: " + message);
}); content.receiveText("Client connected, ready to send/receive messages!");
output("Connected to WebChannel, ready to send/receive messages!");
});
} //END SETUP
</script>
<style type="text/css">
html {
height: %;
width: %;
}
#input {
width: 400px;
margin: 10px ;
}
#send {
width: 90px;
margin: ;
}
#output {
width: 500px;
height: 300px;
}
</style>
</head>
<body>
<textarea id="output"></textarea><br />
<input id="input" /><input type="submit" id="send" value="Send" onclick="javascript:click();" />
</body>
</html>

    1.6.2、qwebchannel.js

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtWebChannel module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/ "use strict"; var QWebChannelMessageTypes = {
signal: ,
propertyUpdate: ,
init: ,
idle: ,
debug: ,
invokeMethod: ,
connectToSignal: ,
disconnectFromSignal: ,
setProperty: ,
response: ,
}; var QWebChannel = function(transport, initCallback)
{
if (typeof transport !== "object" || typeof transport.send !== "function") {
console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
" Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
return;
} var channel = this;
this.transport = transport; this.send = function(data)
{
if (typeof(data) !== "string") {
data = JSON.stringify(data);
}
channel.transport.send(data);
} this.transport.onmessage = function(message)
{
var data = message.data;
if (typeof data === "string") {
data = JSON.parse(data);
}
switch (data.type) {
case QWebChannelMessageTypes.signal:
channel.handleSignal(data);
break;
case QWebChannelMessageTypes.response:
channel.handleResponse(data);
break;
case QWebChannelMessageTypes.propertyUpdate:
channel.handlePropertyUpdate(data);
break;
default:
console.error("invalid message received:", message.data);
break;
}
} this.execCallbacks = {};
this.execId = ;
this.exec = function(data, callback)
{
if (!callback) {
// if no callback is given, send directly
channel.send(data);
return;
}
if (channel.execId === Number.MAX_VALUE) {
// wrap
channel.execId = Number.MIN_VALUE;
}
if (data.hasOwnProperty("id")) {
console.error("Cannot exec message with property id: " + JSON.stringify(data));
return;
}
data.id = channel.execId++;
channel.execCallbacks[data.id] = callback;
channel.send(data);
}; this.objects = {}; this.handleSignal = function(message)
{
var object = channel.objects[message.object];
if (object) {
object.signalEmitted(message.signal, message.args);
} else {
console.warn("Unhandled signal: " + message.object + "::" + message.signal);
}
} this.handleResponse = function(message)
{
if (!message.hasOwnProperty("id")) {
console.error("Invalid response message received: ", JSON.stringify(message));
return;
}
channel.execCallbacks[message.id](message.data);
delete channel.execCallbacks[message.id];
} this.handlePropertyUpdate = function(message)
{
for (var i in message.data) {
var data = message.data[i];
var object = channel.objects[data.object];
if (object) {
object.propertyUpdate(data.signals, data.properties);
} else {
console.warn("Unhandled property update: " + data.object + "::" + data.signal);
}
}
channel.exec({type: QWebChannelMessageTypes.idle});
} this.debug = function(message)
{
channel.send({type: QWebChannelMessageTypes.debug, data: message});
}; channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
for (var objectName in data) {
var object = new QObject(objectName, data[objectName], channel);
}
// now unwrap properties, which might reference other registered objects
for (var objectName in channel.objects) {
channel.objects[objectName].unwrapProperties();
}
if (initCallback) {
initCallback(channel);
}
channel.exec({type: QWebChannelMessageTypes.idle});
});
}; function QObject(name, data, webChannel)
{
this.__id__ = name;
webChannel.objects[name] = this; // List of callbacks that get invoked upon signal emission
this.__objectSignals__ = {}; // Cache of all properties, updated when a notify signal is emitted
this.__propertyCache__ = {}; var object = this; // ---------------------------------------------------------------------- this.unwrapQObject = function(response)
{
if (response instanceof Array) {
// support list of objects
var ret = new Array(response.length);
for (var i = ; i < response.length; ++i) {
ret[i] = object.unwrapQObject(response[i]);
}
return ret;
}
if (!response
|| !response["__QObject*__"]
|| response.id === undefined) {
return response;
} var objectId = response.id;
if (webChannel.objects[objectId])
return webChannel.objects[objectId]; if (!response.data) {
console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
return;
} var qObject = new QObject( objectId, response.data, webChannel );
qObject.destroyed.connect(function() {
if (webChannel.objects[objectId] === qObject) {
delete webChannel.objects[objectId];
// reset the now deleted QObject to an empty {} object
// just assigning {} though would not have the desired effect, but the
// below also ensures all external references will see the empty map
// NOTE: this detour is necessary to workaround QTBUG-40021
var propertyNames = [];
for (var propertyName in qObject) {
propertyNames.push(propertyName);
}
for (var idx in propertyNames) {
delete qObject[propertyNames[idx]];
}
}
});
// here we are already initialized, and thus must directly unwrap the properties
qObject.unwrapProperties();
return qObject;
} this.unwrapProperties = function()
{
for (var propertyIdx in object.__propertyCache__) {
object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
}
} function addSignal(signalData, isPropertyNotifySignal)
{
var signalName = signalData[];
var signalIndex = signalData[];
object[signalName] = {
connect: function(callback) {
if (typeof(callback) !== "function") {
console.error("Bad callback given to connect to signal " + signalName);
return;
} object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
object.__objectSignals__[signalIndex].push(callback); if (!isPropertyNotifySignal && signalName !== "destroyed") {
// only required for "pure" signals, handled separately for properties in propertyUpdate
// also note that we always get notified about the destroyed signal
webChannel.exec({
type: QWebChannelMessageTypes.connectToSignal,
object: object.__id__,
signal: signalIndex
});
}
},
disconnect: function(callback) {
if (typeof(callback) !== "function") {
console.error("Bad callback given to disconnect from signal " + signalName);
return;
}
object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
var idx = object.__objectSignals__[signalIndex].indexOf(callback);
if (idx === -) {
console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
return;
}
object.__objectSignals__[signalIndex].splice(idx, );
if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === ) {
// only required for "pure" signals, handled separately for properties in propertyUpdate
webChannel.exec({
type: QWebChannelMessageTypes.disconnectFromSignal,
object: object.__id__,
signal: signalIndex
});
}
}
};
} /**
* Invokes all callbacks for the given signalname. Also works for property notify callbacks.
*/
function invokeSignalCallbacks(signalName, signalArgs)
{
var connections = object.__objectSignals__[signalName];
if (connections) {
connections.forEach(function(callback) {
callback.apply(callback, signalArgs);
});
}
} this.propertyUpdate = function(signals, propertyMap)
{
// update property cache
for (var propertyIndex in propertyMap) {
var propertyValue = propertyMap[propertyIndex];
object.__propertyCache__[propertyIndex] = propertyValue;
} for (var signalName in signals) {
// Invoke all callbacks, as signalEmitted() does not. This ensures the
// property cache is updated before the callbacks are invoked.
invokeSignalCallbacks(signalName, signals[signalName]);
}
} this.signalEmitted = function(signalName, signalArgs)
{
invokeSignalCallbacks(signalName, signalArgs);
} function addMethod(methodData)
{
var methodName = methodData[];
var methodIdx = methodData[];
object[methodName] = function() {
var args = [];
var callback;
for (var i = ; i < arguments.length; ++i) {
if (typeof arguments[i] === "function")
callback = arguments[i];
else
args.push(arguments[i]);
} webChannel.exec({
"type": QWebChannelMessageTypes.invokeMethod,
"object": object.__id__,
"method": methodIdx,
"args": args
}, function(response) {
if (response !== undefined) {
var result = object.unwrapQObject(response);
if (callback) {
(callback)(result);
}
}
});
};
} function bindGetterSetter(propertyInfo)
{
var propertyIndex = propertyInfo[];
var propertyName = propertyInfo[];
var notifySignalData = propertyInfo[];
// initialize property cache with current value
// NOTE: if this is an object, it is not directly unwrapped as it might
// reference other QObject that we do not know yet
object.__propertyCache__[propertyIndex] = propertyInfo[]; if (notifySignalData) {
if (notifySignalData[] === ) {
// signal name is optimized away, reconstruct the actual name
notifySignalData[] = propertyName + "Changed";
}
addSignal(notifySignalData, true);
} Object.defineProperty(object, propertyName, {
configurable: true,
get: function () {
var propertyValue = object.__propertyCache__[propertyIndex];
if (propertyValue === undefined) {
// This shouldn't happen
console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
} return propertyValue;
},
set: function(value) {
if (value === undefined) {
console.warn("Property setter for " + propertyName + " called with undefined value!");
return;
}
object.__propertyCache__[propertyIndex] = value;
webChannel.exec({
"type": QWebChannelMessageTypes.setProperty,
"object": object.__id__,
"property": propertyIndex,
"value": value
});
}
}); } // ---------------------------------------------------------------------- data.methods.forEach(addMethod); data.properties.forEach(bindGetterSetter); data.signals.forEach(function(signal) { addSignal(signal, false); }); for (var name in data.enums) {
object[name] = data.enums[name];
}
} //required for use with nodejs
if (typeof module === 'object') {
module.exports = {
QWebChannel: QWebChannel
};
}

2、Z01.html

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8"> <script type="text/javascript" >
<!-- window.onload = function()
{
}; -->
</script> </head> <body> <ahref="javascript:document.getElementByIdx_x("myLabel").setText("通过JavaScript访问Qt对象");"mce_href="javascript:document.getElementByIdx_x("myLabel").setText("通过JavaScript访问Qt对象");">点击访问Qt对象</a> </body>
</html>

3、

QWebEngine_C++_交互的更多相关文章

  1. (尚029)Vue_案例_交互footer组件功能

    需要实现界面截图: 难点分析:sAllCheck必须定义为计算属性 1.想到问题: 一旦写一个组件,需要接收哪些属性?? 因为只有属性确定了,标签才好写 todos属性可以确定三个方面的显示 2.做交 ...

  2. (尚027)Vue_案例_交互添加

    TodoHeader.vue组件 写交互: 第一步:跟目标元素绑定监听 (1).按回车键确认@keyup.enter="add" (2). 注意:数据在哪个组件,更新数据的行为就应 ...

  3. (尚024)Vue_案例_交互删除

    注意:本总结中最终会删除不成功 ,原因是Item.vue中方法methods单词拼写错误!!! 首先明白,删除在Item.vue中交互 1.写交互,首先写监听@click="deleteIt ...

  4. (尚023)Vue_案例_交互添加

    最终达到效果: 1.做交互,首先需要确定操作哪个组件? 提交------操作组件Add.vue 2.从哪开始做起呢? 从绑定事件监听开始做起,确定你跟谁绑定事件监听,在回调函数中做什么, ====== ...

  5. (尚028)Vue_案例_交互删除

    删除一条;1.鼠标移入移除这一条时颜色有变化 2.删除当前的todo ================================================================= ...

  6. python小题目汇总

    1.编程计算两个日期之间的天数与周数 Python时间处理---dateutil模块: dateutil模块主要有两个函数,parser和rrule. 其中parser是根据字符串解析成datetim ...

  7. Flutter实战视频-移动电商-31.列表页_列表切换交互制作

    31.列表页_列表切换交互制作 博客地址:https://jspang.com/post/FlutterShop.html#toc-c42 点击左侧的大类右边的小类也跟着变化 新建provide 要改 ...

  8. Flutter实战视频-移动电商-32.列表页_小类高亮交互效果制作

    32.列表页_小类高亮交互效果制作 点击大类右侧的横向的小类红色显示当前的小类别 解决之前溢出的问题: 先解决一个bug,之前右侧的这里设置的高度是1000,但是有不同的虚拟机和手机设别的问题造成了溢 ...

  9. Flutter实战视频-移动电商-33.列表页_子类和商品列表交互效果

    33.列表页_子类和商品列表交互效果 主要实现点击小类下面的列表跟着切换 获取右侧下面的列表信息,即要传递大类的id也要传递小类的,所以需要把左侧的大类的id也要Provide化 可以看下网站上的接口 ...

随机推荐

  1. 安装MySQL与安装Hive

    安装mysql 检查是否安装mysql: rpm -qa |grep mysql 删除已经安装的mysql: rpm -e mysql-libs-5.1.71-1.el6.x86_64 报错:因为my ...

  2. 数据去重优化 MemoryError 内存不足

    from ProjectUtil.usingModuleTOMODIFY import getNow export_q_f, q_l, start_ = '/mnt/mongoexport/super ...

  3. mysql数据库建模Navicat

    用Navicat制作ER图及与SQL互相转化 http://wangbaiyuan.cn/sql-and-use-navicat-to-make-er-diagram-and-interactive. ...

  4. PHP之设计模式

    https://blog.csdn.net/self_realian/article/details/78228733 掌握PHP各类设计模式,具备设计纯面向对象框架和系统能力是非常有必要的.给大家一 ...

  5. mysqldump 导出统一限制每张数据表导出的记录数

    mysqldump 导出统一限制每张数据表导出的记录数 在工作过程中,需要将生产的数据导出到本地开发环境,我希望可以导出部分数据.而服务器数据量比较大(上千万),如果选择直接从服务器导出数据, 正在运 ...

  6. loadrunner11的移动端性能测试之场景设计

    测试步骤之场景设计(Controller) 进入手工场景 准备好脚本后就可以进行场景设计和执行场景了,从VuGen中进入,见下图: 进入后第一个为目标场景,选择第二个更灵活的手工场景,我的目标人数20 ...

  7. HDU1573:X问题(解一元线性同余方程组)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1573 题目解析;HDU就是坑,就是因为n,m定义成了__int64就WAY,改成int就A了,无语. 这题 ...

  8. Selenium之firefox浏览器的启动问题及解决

    启动firefox报错如下: rg.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 ...

  9. R语言基本语法

    R语言基本语法 基本数据类型 数据类型 向量 vector 矩阵 matrix 数组 array 数据框 data frame 因子 factor 列表 list 向量 单个数值(标量)没有单独的数据 ...

  10. (25)HttpClient session

    session概述 session机制 session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息. 当程序需要为某个客户端的请求创建一个session ...