Posted  by  admin

Qt Call Slot From Different Thread

As Qt WebKit is replaced by Qt WebEngine(you can refer to this post about porting issues), accessing html elements from C++ directly becomes impossible. Many works originally done by QWebKit classes are now transferred to javascript. Javascript is used to manipulate web content. And you need to call runJavaScript from C++ code to run javascript on the web page loaded by QWebEngineView.To get web elements, a communication mechanism is invented to bridge the C++ world and the javascript world. The bridging mechanism is more than obtaining the values of web page elements. It provides the ways in which C++ code can call javascript functions, and javascript can invoke C++ functions as well.The values of variables can also be passed from C++ to javascript, and vice versa. Let’s consider the following application scenarios:

Two threads with an object assigned to each thread’s event loop. Each event loop handles events by invoking corresponding functions on the object. Notice how another object’s methods can still be called from another thread directly. (calling userFunction) To complete this article, let’s look at running our code on other threads. Qt supports four types of signal-slot connections: 1) With direct connections, the slot gets called immediately when the signal is emitted. The slot is executed in the thread that emitted the. I use Qt::QueuedConnection to execute this slot. Once in a while, the Master has to ask Worker to stop the calculation in between, and to terminate it prematurely I have provided the abortCalculation variable in the Worker object which it checks in each loop of the long-running calculation. The event will be deleted right after being processed in the thread that processes it. An event posted using a QueuedConnection is a QMetaCallEvent. When processed, that event will call the slot the same way we call them for direct connections. All the information (slot to call, parameter values.) are stored inside the event. Qt's event systemis very useful for inter-thread communication. Every thread may have its own event loop. To call a slot (or any invokablemethod) in another thread, place that call in the target thread's event loop.

javascript code calls C++ function

C++ code should provide a class which contains the to-be-called function(as a slot), then register an object of this class to a QWebChannel object, and set the web channel object to the web page object in the QWebEngineView

To invoke the C++ function jscallme, javascript should new an instance of QWebChannel object.

QWebChannel is defined in qwebchannel.js(you can find this file in the example folder of Qt installation directory) so the script should be loaded first. In the function passed as the second parameter of function QWebChannel, the exposed object from C++ world(webobj in C++) channel.objects.webobj is assigned to the javascript variable webobj, and then assigned to window.foo so you can use foo elsewhere to refer to the object. After the function is executed, javascript can call the C++ slot function jscallme as follows:

Pass data from javascript to C++

We’ve known how to call C++ function from javascript. You should be able to figure out a way to pass data from javascript to C++, i.e., as parameter(s) of function. We re-implement jscallme as follows:

, and invoking of the function from js would be:

Slot

Note that the “const” before the parameter can not be omitted, otherwise, you will get the following error:
Could not convert argument QJsonValue(string, “sd”) to target type .

Although data can be passed as parameters of function, it would be more convenient if we can pass data by setting an attribute of an object like:

We expect after the code is executed, “somedata” will be stored in a member variable of the exposed object (webobj) in C++. This is done by delaring a qt property in C++ class:

Now if you execute foo.someattribute=”somedata” in javascript, m_someattribute in C++ will be “somedata”.

Pass data from C++ to javascript

Qt Call Slot From Different Thread Type

We can send data from C++ to javascript using signals. We emit a signal with the data to send as the parameter of the signal. Javascript must connect the signal to a function to receive the data.

The line “webobj.someattributeChanged.connect(updateattribute)” connects the C++ signal someattributeChanged to the javascript function updateattribute. Note that although updateattribute takes one parameter “text”, we did not provide the parameter value in connect. In fact, we do not know the parameter value passed to updateattribute until the signal is received. The signal is accompanied by a parameter “attr” which is passed as the “text” parameter of updateattribute. Now, if you call webobj->setsomeattribute(“hello”), you will see the value of the html element with id “#attrid” is set to “hello”. Note that although we connect the member m_someattribute to the qt property someattribute in the above example, it is not a required step. The signal mechanism alone can realize the delivery of data.
We can make things even simpler by adding the NOTIFY parameter when declaring the someattribute property.

Now, if you call webobj->setProperty(“someattribute”,”hello”) somewhere in C++, the signal “someattributeChanged” is automatically emitted and our web page gets updated.

C++ invokes javascript function

This is much straightforward compared with invoking C++ function from js. Just use runJavaScript passing the function as the parameter as follows:

Another

Qt Call Slot Thread

It assumes the jsfun is already defined on your web page, otherwise, you have to define it in the string parameter. The return value is asynchronously passed to the lambda expression as the parameter v.

Qt Call Slot From Different Threads

Now, back to the question raised at the beginning of the post: How to get the value of an html element in C++? It can be done as follows:

It uses jQuery functions so make sure jQuery lib is running on your web page.

Qt Call Slot From Different Thread Types

If you like my content, please consider buying me a coffee. Thank you for your support!