Русскоязычный портал о QML и QtQuick, QmlPortal What the duck

Каталог статей

Главная » Статьи » Статьи по QML

Интеграция QML и C++
Интеграция QML и C++

В простом случае интеграция может осуществляться с помощью виджета QDeclarativeView. Он является наследником QGraphicsView и уже включает в себя необходимые компоненты для встраивания QML-приложения. Другой подход состоит в построении новых типов C++, доступных в среде выполнения QML, с помощью плагинов. При использовании в QML такие типы обладают теми же возможностями, как и в C++-приложении.

В более сложных ситуациях способ интеграции QML в C++ зависит от структуры кода на C++.
Если имеется приложение, использующее виджеты C++, то можно использовать все доступные графические компоненты и переписать все классы, основанные на QWidget, на QML без изменения функциональности приложения. Поскольку в этом случае уже есть готовая архитектура приложения, дальнейшие шаги в разработке на QML будут относительно простыми.

Если же приложение основано на QGraphicsView, то процесс преобразования еще проще и может осуществляться в несколько этапов. Можно поместить целое QML-приложение в существующее графическое представление путём создания QML-движка (QML engine). Кроме того, можно использовать тот факт, что интерфейс QML может сосуществовать с пользовательским интерфейсом на C++. Это позволяет производить процесс преобразования пошагово.

Три шага, необходимые для создания QML-движка и контекста с существующим QGraphicsView:
1) создаётся объект класса QDeclarativeEngine, представляющий собой окружение для порождения QML-компонентов
2) QML-код компонента помещается в специальный компонент — объект класса QDeclarativeComponent
3) На базе компонента создаётся объект, являющийся наследником класса QGraphicsObject, который может быть добавлен к существующей сцене. Таким образом, он будет сосуществовать с остальной частью пользовательского интерфейса.

QGraphicsScene *scene = ...;

QDeclarativeEngine *engine = new QDeclarativeEngine;
QDeclarativeComponent component(engine, QUrl::fromLocalFile(...));
QGraphicsObject *object =
qobject cast<QGraphicsObject*>(component.create());

scene->addItem(object);


Если компонент не может загрузить QML-файл, то значение свойства error будет равно true. Чтобы выводить сообщения об ошибках, надо поместить следующую строку кода после вызова метода create ():
qWarning() << component.errors();

Описанный выше код можно использовать только, если в проект подключен <QtDebug>. См. документацию по qWarning () для более детального изучения.

Для выравнивания элементов пользовательского интерфейса можно изменить значение параметра z QGraphicsObject, чтобы поместить элемент в соответствующей глубине сцены. Для достижения оптимальной производительности пользовательского интерфейса QML, рекомендуется установить следующие опции:

QGraphicsView *view = ...;

view->setOptimizationFlags(QGraphicsView::DontSavePainterState);
view->setViewportUpdateMode(
QGraphicsView::BoundingRectViewportUpdate);
view->setItemIndexMethod(QGraphicsScene::NoIndex);



Обмен данными между C++ и QML

Qt Quick предоставляет множество способов обмена данными между C++ и QML, как используя реализацию стандартного шаблона проектирования "model-view", так и не применяя ее. Кроме того, можно вызывать QML-функции из C++ и наоборот. В общем, поскольку все элементы унаследованы от QObject, все их сигналы, слоты и свойства доступны в QML.

Весь код на QML выполняется через контекст. Контекст отслеживает, какие данные доступны для различных листьев и узлов в дереве (иерархии) объектов QML. Данные передаются как свойства контекста или объекты контекста. Свойство контекста - это простой способ определить объект, задавая имя этого объекта.
Например, чтобы определить объект класса класса QColor как свойство с именем frameColor в QML, можно просто использовать следующий код:

QDeclarativeContext *context = ...;
context->setContextProperty("frameColor", QColor(Qt::red));


Это свойство может быть доступно через QML-контекст как глобальное свойство, как показано ниже. Следует помнить, что в QML значения свойств привязываются, а не присваиваются. Это означает, что можно изменить свойство frameColor в C++-коде, и эти изменения будут отображены в QML.

Rectangle {
       border.color: frameColor
}


Можно добавить несколько контекстных свойств в объект класса QDeclarativeContext, однако с увеличением списка свойств ухудшается понятность кода. Поэтому вместо того чтобы задавать каждое свойство отдельно, лучше собрать все контекстные свойства в одном объекте QObject и установить его в качестве контекстного объекта.

Следующий код показывает, как определить объект интерфейса MyInterface, используя метод setContextProperty (). Макрос Q_PROPERTY определяет свойства, доступные через объект класса MyInterface из системы свойств библиотеки Qt и задает сигналы, которые могут быть использованы далее в работе.

Отметим, что все свойства, добавленные явно при помощи QDeclarativeContext:: setContextProperty (), имеют более высокий приоритет, чем свойства контекстного объекта по умолчанию.

class MyInterface : ... {
...
       Q PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
...
};


MyInterface *myInterface = new MyInterface;
QDeclarativeEngine engine;
QDeclarativeContext *context = new
QDeclarativeContext(engine.rootContext());
context->setContextObject(myDataSet);
QDeclarativeComponent component(&engine);
component.setData("import Qt 4.7\nListView { model: myModel }", QUrl());
component.create(context);



QML-представления в моделях на C++

Свойства объекта хорошо работают, когда набор их значений в QML ограничен, но ими становится трудно управлять, когда появляются большие объемы данных. В этих случаях формальные модели визуализируются при помощи формальных представлений. Этот шаблон проектирования "model/view" позволяет разработчикам отделять реализацию пользовательского интерфейса от бизнес-логики. Модель может быть реализована на языке С++, в то время как представление написано на QML.

QML может создавать представления для моделей на C++, которые являются наследниками класса QAbstractItemModel.

Чтобы работать с QAbstractItemModel в QML, надо использовать контекстное свойство:

QAbstractItemModel *model = ...;
context->setContextProperty("dataModel", model);


Класс QAbstractItemModel в библиотеке Qt предоставляет абстрактный интерфейс для классов модели. Этот класс определяет стандартный интерфейс для моделей, которые могут взаимодействовать с другими компонентами в архитектуре "модель-представление". Нельзя создать объект класса QAbstractItemModel. Необходимо определить наследника этого класса, чтобы создавать новые модели.

Класс QAbstractItemModel входит в Model/View Classes и является частью Qt model/view framework.


Программирование на QML / C++

Qt Quick позволяет QML вызывать методы, написанные на C++, и дает возможность обрабатывать C++-сигналы при помощи выражений на JavaScript через контекст QML.

Вызов C++-методов в QML

Для передачи данных от пользователя к бизнес-логике, QML должен иметь возможность вызывать C++-методы. Это достигается с помощью слотов или методов Q_INVOKABLE. Обеспечив QML доступ к QObject как к контекстному свойству, слоты и методы Q_INVOKABLE соответствующего класса могут быть вызваны из QML.

Например, приведенный ниже класс-наследник QObject добавляется в QML как контекстное свойство.

class CallableClass : public QObject
{
      Q_OBJECT
      ...
      public slots:
      void cppMethod() { qDebug(”C++ method called!”); }
};

...

context->setContextProperty(”cppObject”, new CallableClass);


Теперь в QML-коде можно обратиться к методу cppMethod при помощи глобального объекта cppObject. В этом примере метод не возвращает никакого значения и не принимает каких-либо аргументов, но это не запрещено в QML. QML поддерживает все возможные в нем типы возвращаемых значений и аргументов.

MouseArea {
      ...
      onClicked: {
           cppObject.cppMethod();
      }
}


Обработка Qt-сигналов в QML

Qt C++ сигналы могут быть обработаны с помощью выражений на языке JavaScript в QML-контексте. Пусть класс CallableClass из предыдущего примера также содержит свой сигнал: cppSignal ().

class CallableClass : public QObject
{
      Q_OBJECT
      ...
      signals:
      void cppSignal();
};


Сигнал может быть обработан в QML при помощи элемента Connections. Этот элемент может быть использован для обработки сигналов любого целевого объекта, в том числе и других элементов QML. Обработчик сигнала будет называться onSignalName. Здесь первая буква в имени сигнала становится заглавной.

Connections {
       target: cppObject

       onCppSignal: { console.log("QML function called!"); }

}

Расширение QML с помощью C++


В QML есть встроенная поддержка для обширного набора типов элементов, но, когда конкретное приложение нуждается в поддержке собственных классов, можно дополнить возможности QML с помощью пользовательских типов элементов, написанных на C++. Например, необходимо создать QML-элемент, который называется Person и имеет свойства name и shoeSize.

Все QML-элементы имеют однозначное соответствие с типами C++. В листинге 1 объявляется класс Person на С++ с двумя свойствами: name и shoeSize, которые должны быть доступны в типе QML. Хотя в этом примере для C++-класса используется то же имя, что и для элемента QML, C++-класс может иметь и другое название, или находиться в другом пространстве имен.

class Person : public QObject
{
      Q_OBJECT
      Q_PROPERTY(QString name READ name WRITE setName)
      Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)

      public:
           Person(QObject *parent = 0);

           QString name() const;
           void setName(const QString &);

           int shoeSize() const;
           void setShoeSize(int);

       private:
           QString m_name;
           int m_shoeSize;
};

Person::Person(QObject *parent): QObject(parent), m_shoeSize(0)
{
}

QString Person::name() const
{
        return m_name;
}

void Person::setName(const QString &n)
{
        m_name = n;
}

int Person::shoeSize() const
{
        return m_shoeSize;
}

void Person::setShoeSize(int s)
{
         m_shoeSize = s;
}


Реализация класса Person вполне стандартная. Его методы просто возвращают значения полей.

В файле main.cpp также вызывается функция qmlRegisterType(), чтобы зарегистрировать тип Person в QML как тип в библиотеке People версии 1.0, и определяется соответствие между названиями класса в C++ и в QML.

Теперь тип Person может быть использован в QML:

import People 1.0

Person {
        name: "Bob Jones"
        shoeSize: 12
}


Источник: http://qt.nokia.com/files/pdf/qt-quick-for-c-developers
Категория: Статьи по QML | Добавил: CYAN (29.06.2011) | Автор: C_Y_A_N E W
Просмотров: 18612 | Теги: Q_INVOKABLE, Интеграция QML и C++, QML, QGraphicsView, C++ | Рейтинг: 5.0/7
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Категории раздела

Все статьи [0]
Обучение QML [8]
Статьи с базовой информацией о языке QML
Статьи по QML [6]
Статьи по QML
QML для профессионалов [4]
Статьи по QML-темам повышенной сложности
Ссылки на видео [5]
Ссылки на видео с демонстрацией возможностей QML
Ссылки на материалы по QML в интернете [2]
Ссылки на полезные материалы по QML в интернете
Обо всём [1]
Статьи на разные темы, не имеющие отношение к QML и QtQuick

Поиск на сайте

Облако тэгов

kinetic scroll анимация интерфейса кинетик скролл создание интерфейса path view qml видео демонстрация qml QML Component QML Grid Demo QML browser plugin просмотр QML форм QML signal QML Transition базовые типы QML QML Text пример QML экспорт qml из GIMP QML Rectangle color picker QML MouseArea qml export QML State экспорт QML из Photoshop QML QtQuick Web-browser Набор виджетов для QML статьи о QML на русском языке MeegoHarmattan N9/N950 game Sprite Animation GLSL fragment shader Qt Quick 2 Анимация Easing Easing curves Сглаживающие кривые C++ QGraphicsView Q_INVOKABLE Интеграция QML и C++ QML Particle System QtQuick.Particles QML Scene Graph javascript глобальные переменные Qt Mobility QtMultimediaKit map QtMobility.location Debian package Harmattan QtCreator D.U.C.K. H.U.N.T. QML пример

Статистика сайта

Статей: 26
Новостей: 6
Файлов: 10
Форум: 19/46
Коментариев: 6

Посетители

Полезные ресурсы

сайт Российского Qt сообщества The FRUCT program Российская сеть MeeGo пользователей и разработчиков