📜 ⬆️ ⬇️

QML and C ++. We chase the data, we estimate the speed of interaction

About how to send data from QML to C ++ and after manipulating them to return them (data) back, it has already been repeatedly told . Most articles provide the same examples or, at best, slightly modified by the authors of the articles.

Let's look at a couple of the most explicit ways to transfer data from QML to C ++ and vice versa. We also estimate their effectiveness.

Well, let's start


We take the simplest thing that can come to mind: there is a window with text, when you click on the text, we need to do some manipulations with this text using c ++ tools and then show the final version in the same window.
')
The first version of the implementation of such a complex task: from QML we call the slot described in the C ++ class and pass it our text. After changing the text, we call the signal and along with this signal we transmit the modified text to QML.

File main.cpp | We create an instance of a class in which our signal and slot are described, we declare a context property (as if we pass a link to our class in qml)
#include <QApplication> #include "qmlapplicationviewer.h" #include <QDeclarativeContext> #include "asd.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); QmlApplicationViewer viewer; asd ASD; viewer.rootContext()->setContextProperty("ASD", &ASD); viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/habr1/main.qml")); viewer.showExpanded(); return app->exec(); } 


File asd.h (header of our class with signal and slot)
 #ifndef ASD_H #define ASD_H #include <QObject> class asd : public QObject { Q_OBJECT public: explicit asd(QObject *parent = 0); signals: void transmitNewText(QString text); public slots: void getOldText(QString text); }; #endif // ASD_H 


File asd.cpp (we describe our slot) | As can be seen from the code, the slot accepts the text, adds the word to it and then calls the signal
 #include "asd.h" asd::asd(QObject *parent) : QObject(parent) { } void asd::getOldText(QString text){ emit transmitNewText(text + " Hello!"); } 


Well, main.qml (our window with the text) | By clicking the mouse button (onClicked), we call the slot and wait for the signal (onTransmitNewText) upon receipt of which we change the text of the message in our window
 import QtQuick 1.1 Rectangle { width: 360 height: 360 Connections { target: ASD onTransmitNewText: text1.text = text } Text { id: text1 text: qsTr("Hello World.") anchors.centerIn: parent } MouseArea { anchors.fill: parent onClicked: ASD.getOldText(text1.text) } } 


At this boring part ends. Let's turn it on and see how long it takes to call a slot and send our modified text with a signal.



For the purity of the experiment, click on the text 20 times:


We see two lines called “Signals”. Open the timeline, make sure that to estimate the speed of the whole process, we need only the top line from our picture, since namely, it lasts from the beginning of the call to the time the signal is sent:


The second embodiment: when you click on the text, we generate a signal, connect this signal to the slots of a class already familiar to us, after which we call the same signal all the same way after changing the text and respond to it with the slot described in QML.

At first glance it may seem that this will take more time than in the first version.

We change our main.cpp (everything is simple and clear here, we connect slots and signals)
 #include <QApplication> #include "qmlapplicationviewer.h" #include <QGraphicsObject> #include "asd.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/habr2/main.qml")); asd ASD; QObject *qml = viewer.rootObject(); QObject::connect(qml, SIGNAL(transmitOldText(QString)), &ASD, SLOT(getOldText(QString))); QObject::connect(&ASD, SIGNAL(transmitNewText(QVariant)), qml, SLOT(getNewText(QVariant))); viewer.showExpanded(); return app->exec(); } 


asd.h (slightly change the heading of our class) | because In qml, when defining a function, you cannot explicitly specify the data type, you have to replace QString with QVariant
 #ifndef ASD_H #define ASD_H #include <QObject> #include <QVariant> class asd : public QObject { Q_OBJECT public: explicit asd(QObject *parent = 0); signals: void transmitNewText(QVariant text); public slots: void getOldText(QString text); }; #endif // ASD_H 


asd.cpp (added the same QVariant )
 #include "asd.h" asd::asd(QObject *parent) : QObject(parent) { } void asd::getOldText(QString text){ emit transmitNewText(QVariant(text + " Hello!")); } 


Well, our new window main.qml
 import QtQuick 1.1 Rectangle { id: rth width: 360 height: 360 function getNewText(text){ text1.text = text } signal transmitOldText(string text) Text { id: text1 text: qsTr("Hello World.") anchors.centerIn: parent } MouseArea { anchors.fill: parent onClicked: transmitOldText(text1.text) } } 


Check how much time we need this time:


At the request of readers, we add to our testing function that returns the value


So, main.cpp remains exactly as it was in the first version. All the context property is also declared (reference to an instance of our class)
 asd ASD; viewer.rootContext()->setContextProperty("ASD", &ASD); 


Slightly change our C ++ slot (now it returns a value)
 QString asd::getOldTextTransmitNewText(QString text){ return text + " Hello!"; } 


Then we change main.qml a little
 MouseArea { anchors.fill: parent onClicked: text1.text = ASD.getOldTextTransmitNewText(text1.text) } 


Turn on, look at the time spent:


Same option, only with Q_INVOKABLE
 Q_INVOKABLE QString getOldTextTransmitNewText(QString text); 


It turns out quite a bit slower slots:


Summing up (I remind you that the milliseconds given are the sum for 20 calls)


The longest was the first method (calling a slot from qml followed by catching the signal): 14.885 ms .
The second option (where we connected slots and signals) turns out to be faster: 13.993 ms .
The fastest option is to call a function that returns a value: 13.456 ms . for slot and 13.508 ms . for Q_INVOKABLE (within the margin of error).

Yes, the thing, of course, is not very noticeable, but no one expected the difference in milliseconds at 20. You can refer to the error, but with repeated repetition of this experiment, if I may say so, the experiment, the result turned out to be approximately equal to that given in this article.

Why and for whom was all this done? For some reason this thought came to my mind, for I had never dealt with such “nonsense”. Well, after I decided to share the results with you.

Source: https://habr.com/ru/post/171341/


All Articles