Давайте рассмотрим пару самых явных способов передавать данные из QML в C++ и обратно. Также оценим их эффективность.
Ну, пожалуй, начнем
Берем самое простое, что может прийти в голову: есть окно с текстом, при нажатии на текст, нам нужно сделать какие-нибудь манипуляции с этим текстом средствами c++ и после показать конечный вариант в этом же окне.
Первый вариант реализации столь сложной задачи: из QML вызываем слот, описанный в C++ классе и передаем ему наш текст. После изменения текста вызываем сигнал и вместе с этим сигналом передаем измененный текст в QML.
Файл main.cpp | Создаем экземпляр класса, в котором описаны наш сигнал и слот, декларируем контекстное свойство (как бы передаем ссылку на наш класс в 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(); }
Файл asd.h (заголовок нашего класса с сигналом и слотом)
#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
Файл asd.cpp (описываем наш слот) | Как видно из кода, слот принимает текст, добавляет к нему слово и после вызывает сигнал
#include "asd.h" asd::asd(QObject *parent) : QObject(parent) { } void asd::getOldText(QString text){ emit transmitNewText(text + " Hello!"); }
Ну и main.qml (наше окно с текстом) | По нажатию кнопки мыши (onClicked) вызываем слот и ждем сигнал (onTransmitNewText) при получении которого меняем текст сообщения в нашем окне
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) } }
На этом скучная часть заканчивается. Давайте это включим и посмотрим, сколько времени требуется на вызов слота и отправку нашего измененного текста с сигналом.
Для чистоты эксперимента кликнем на тексте 20 раз:
Видим две строки, называющиеся «Сигналы». Открываем временную шкалу, убеждаемся, что для оценки скорости всего процесса нам нужна только верхняя строка с нашей картинки т.к. именно она длится с самого начала вызова слота до момента завершения отправки сигнала:
Второй вариант реализации: при нажатии на текст генерируем сигнал, соединяем этот сигнал со слотам уже знакомого нам класса, после чего все тем же путем после изменения текста вызываем все тот же сигнал и отвечаем на него слотом, описанным в QML.
На первый взгляд может показаться, что для этого потребуется больше времени, чем в первом варианте.
Изменяем наш main.cpp (тут все просто и понятно, соединяем слоты и сигналы)
#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 (немного изменяем заголовок нашего класса) | т.к. в qml определяя функцию нельзя явно указать тип данных, придется заменить QString на 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 (добавлен все тот же QVariant)
#include "asd.h" asd::asd(QObject *parent) : QObject(parent) { } void asd::getOldText(QString text){ emit transmitNewText(QVariant(text + " Hello!")); }
Ну и наше новое окно 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) } }
Проверим, сколько времени нам понадобится на этот раз:
Подводим итог: разница во времени составила примерно 0.9 мс Да, штука, конечно, не шибко заметная, но никто ведь не ожидал отличий миллисекунд эдак в 20. Можно сослаться на погрешность, но при многократном повторении сего, если можно так сказать, эксперимента, результат оказывался примерно равен приведенному в этой статье.
Зачем и для кого все это делалось? Мне в голову почему-то пришла именно эта мысль, ибо такой вот «ерундой» я никогда еще не занимался. Ну а после решил поделиться результатами с вами.
ссылка на оригинал статьи http://habrahabr.ru/post/171341/
Добавить комментарий