C++/Javascript互操作
QCefView提供C++/Javascript互操作的能力,因此开发者可以从C++中调用Javascript代码,反之亦然。
互操作能力是通过在QCefView所创建的所有Browser和Frame中插入桥接对象实现的。桥接对象提供一些方法用于原生代码和Web代码进行通信,更多详细介绍请参考WebAPIs。
桥接对象被挂载在window对象上,并且可以通过
QCefConfig::setBridgeObjectName
来设置桥接对象的名字。默认的对象名为CefViewClient
从Javascript中调用C++
桥接对象提供以下方法来从Javascript中调用C++:
⚠[废弃]invokeMethod
(name, ...args)
invoke
(name, ...args)
,
当该方法在Javascript中调用后,下面的Qt signal将被触发:
void
invokeMethod
(int browserId,int frameId,const QString & method,const QVariantList & arguments)
⚠ 注意: Javascript方法
invoke
(name, ...args)
是异步
操作,这意味着该方法的调用会立即返回,无论对应的C++ Qt slot是否已经执行完毕。
现在让我们编写一段代码来演示如何从Javascript中调用C++。
添加Javascript代码
添加如下代码在Web页面的\<script>代码块中:
function onInvokeMethodClicked(name, ...arg) {
// invoke C++ code
// ⚠[DEPRECATED]window.CallBridge.invokeMethod(name, ...arg);
window.CallBridge.invoke(name, ...arg);
}
添加如下HTML代码:
<label> Test Case for InvokeMethod </label>
<br />
<input
type="button"
value="Invoke Method"
onclick="onInvokeMethodClicked('TestMethod', 1, false, 'arg3')"
/>
添加C++代码
然后添加如下C++代码用于处理调用请求:
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
{
// ...
// connect the invokeMethod to the slot
connect(cefViewWidget,
SIGNAL(invokeMethod(int, int, const QString&, const QVariantList&)),
this,
SLOT(onInvokeMethod(int, int, const QString&, const QVariantList&)));
// ...
}
void
MainWindow::onInvokeMethod(int browserId, int frameId, const QString& method, const QVariantList& arguments)
{
// extract the arguments and dispatch the invocation to corresponding handler
if (0 == method.compare("TestMethod")) {
QMetaObject::invokeMethod(
this,
[=]() {
QString title("QCef InvokeMethod Notify");
QString text = QString("Current Thread: QT_UI\r\n"
"Method: %1\r\n"
"Arguments:\r\n")
.arg(method);
for (int i = 0; i < arguments.size(); i++) {
// clang-format off
text.append(QString("%1 Type:%2, Value:%3\r\n")
.arg(i)
.arg(arguments[i].typeName())
.arg(arguments[i].toString()));
// clang-format on
}
QMessageBox::information(this->window(), title, text);
},
Qt::QueuedConnection);
} else {
}
}
运行应用
启动应用,可以看到如下界面:
点击Web区域中的按钮,可以看到如下界面:
从C++中调用Javascript
桥接对象提供如下方法支持从C++中调用Javascript:
addEventListener
(name, listener)
removeEventListener
(name, listener)
开发者可以在Javascript中添加任意多的事件监听器,然后在C++中通过以下方法触发这些事件:
public bool
triggerEvent
(const
QCefEvent
& event)
public bool
triggerEvent
(const
QCefEvent
& event,int frameId)
public bool
broadcastEvent
(const
QCefEvent
& event)
⚠ 注意: 以上三个方法的调用全部都是
异步
操作。
编写代码。
添加Javascript代码
添加如下Javascript代码:
function onLoad() {
// Add a event listener to handle the event named 'colorChange'
Window.CallBridge.addEventListener(
// event name
"colorChange"
// event handler
function (color) {
// change the background color
document.getElementById("main").style.backgroundColor = color;
}
);
}
添加如下HTML代码:
<body onload="onLoad()" id="main" class="noselect">
添加C++代码
添加C++代码用于触发事件,这里我们需要给UI增加一个原生的按钮,相关代码不在这里展示。
void
MainWindow::onBtnChangeColorClicked()
{
if (cefViewWidget) {
// create a random color
QColor color(QRandomGenerator::global()->generate());
// create the cef event and set the arguments
QCefEvent event("colorChange");
event.arguments().append(QVariant::fromValue(color.name(QColor::HexArgb)));
// broadcast the event to all frames in all browsers created by this QCefView widget
cefViewWidget->broadcastEvent(event);
}
}
运行应用
启动应用,可以看到如下界面:
点击Native区域的按钮来触发Javascript事件处理器,可以看到如下界面: