Interoperability
QCefView provides the capabilities of interoperability between native context and web context, thus the developer can call Javascript from C++ code easily, vice versa.
The approach of the interoperability was implemented by inserting a bridge object into the web context displayed in all the frames and browsers managed by QCefView. The bridge object provides methods for communicating with native code. For more details please refer to the API reference WebAPIs
The bridge object is mounted at window object, and the object name could be configured through the
QCefConfig::setBridgeObjectName
. The default name isCefViewClient
Call C++ from Javascript
The bridge object provides the following method to invoke C++ code from Javascript
invokeMethod
(name, ...args)
,
When this method gets called from Javascript, the following Qt signal will be emitted
void
invokeMethod
(int browserId,int frameId,const QString & method,const QVariantList & arguments)
⚠ NOTE: The Javascript method
invokeMethod
(name, ...args)
isASYNCHRONOUS
operation, that means the calling from Javascript returns immediately regardless the execution of C++ Qt slot
Now let's write a small piece of code to demonstrate the invocation from Javascript to C++.
Add Javascript Code
First add Javascript code as follows into the \<script> block
function onInvokeMethodClicked(name, ...arg) {
// invoke C++ code
window.CallBridge.invokeMethod(name, ...arg);
}
and add the html code
<label> Test Case for InvokeMethod </label>
<br />
<input
type="button"
value="Invoke Method"
onclick="onInvokeMethodClicked('TestMethod', 1, false, 'arg3')"
/>
Add C++ Code
Then add code in C++ to handle the invocation
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 {
}
}
Run the Application
Now let's run the application.
Click the button in web area to invoke the C++ code
Call Javascript from C++
The bridge object provides the following methods to support calling from C++ code to Javascript
addEventListener
(name, listener)
removeEventListener
(name, listener)
The developers can add as many event listeners as they want in the Javascript context and trigger the events from C++ code with the following methods
public bool
triggerEvent
(const
QCefEvent
& event)
public bool
triggerEvent
(const
QCefEvent
& event,int frameId)
public bool
broadcastEvent
(const
QCefEvent
& event)
⚠ NOTE: All the 3 methods above are
ASYNCHRONOUS
operations
Now let's code it
Add Javascript Code
Add code to the 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;
}
);
}
Add code to the html
<body onload="onLoad()" id="main" class="noselect">
Add C++ Code
Add code to trigger the event be handled in Javascript, here we need to add a button in perform the triggering, we just show the button click action handler slot.
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);
}
}
Run the Application
Now let's run the application.
Click the button in native area to invoke the Javascript code