Pull to refresh

Первые шаги с QML

Reading time 6 min
Views 26K
QML — это новый язык разметки для создания пользовательских интерфейсов. Его основная задача — обеспечить возможность простого и быстрого создания приложений с красивым, анимированным интерфейсом.
Не так давно вышла публичная версия. Это означает, что API в целом стабилизировался, и версию можно смело тестировать и использовать.
Declarative UI планируется включить в релиз Qt 4.7, а пока можно найти все необходимые файлы и инструкции по установке на ftp троллей.
В данной статье мне хотелось бы показать, как можно использовать С++ объекты (QObject) в qml.


Первым делом нужно скачать с ftp и собрать qt-4.6.0-declarative.tar.gz. А качестве альтернативы можно использовать уже собранный QtCreator, в котором присутствуют нужные библиотеки
Давайте создадим проект:
Проще всего создать через QtCreator GUI приложение Qt4, в качестве базового класса прекрасно подойдет QWidget

qmltest.pro


SOURCES += main.cpp \
widget.cpp \
myobject.cpp
HEADERS += widget.h \
myobject.h
#не забываем добавить эти два значения, иначе компилятор просто не найдет модуль qt-declarative
QT += declarative \
script
#INCLUDEPATH += #Возможно может пригодится, просто укажите путь до директории include/qt-declarative/

Заголовочный файл нашего виджета

widget.h


#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
class QmlView;
class MyObject;
class Widget : public QWidget
{
  Q_OBJECT
public:
  explicit Widget(QWidget *parent = 0);
private:
  QmlView *view;
  MyObject *object;
private slots:
  void onSceneResized(QSize size);
};

#endif // WIDGET_H

* This source code was highlighted with Source Code Highlighter.


Для начала, неплохо было бы убрать системный заголовок и сделать фон прозрачным:
  setWindowFlags(Qt::FramelessWindowHint);
  setAttribute(Qt::WA_TranslucentBackground);
  setAttribute(Qt::WA_NoSystemBackground);
  view = new QmlView(this);
  view->viewport()->setAutoFillBackground(false);


* This source code was highlighted with Source Code Highlighter.

Теперь инициализируем наш просмотрщик QML и указываем ему путь к файлу, который мы собираемся исполнить
  view->setFocus();
  QString filename = qApp->applicationDirPath() + "/qmlpopups/default/popup.qml";
  view->setUrl(QUrl::fromLocalFile(filename));//url - main.qml


* This source code was highlighted with Source Code Highlighter.

Теперь наступает самое интересное: сделать свойства C++ объекта видимыми из qml файла. Для этого необходимо, чтобы объект наследовался от QObject'а. С помощью макроса Q_PROPERTY свойства делаются доступными из qml объектов и javascript'ов
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)

* This source code was highlighted with Source Code Highlighter.

READ указывает, какой функцией пользоваться для получения значения
WRITE указывает, какая функция используется для изменения
NOTIFY указывает, какой сигнал вызывается при изменении значения, используется в биндингах
Подготовив соответствующим образом объект, мы сможем получить доступ к этим свойствам из qmlя.
  view->rootContext()->setContextProperty("MyObject",object);
  view->rootContext()->setContextProperty("MyText","Hello, QML!");
  view->rootContext()->setContextProperty("Avatar",qApp->applicationDirPath() + "/qmlpopups/default/star.png");


* This source code was highlighted with Source Code Highlighter.

Добавление новых объектов осуществляется через QmlContext, указатель на который возращает функция rootContext(). Можно добавлять как отдельные свойства, так и целые объекты.
Теперь перейдем собственно к qml файлу:
Rectangle {
  id: rect
  width:250
  height: 100
  height: Behavior { NumberAnimation { duration: 1000; easing: "InOutQuad" } }
  color: "transparent"

* This source code was highlighted with Source Code Highlighter.

Код рисует нам прямоугольник 250х100 с прозрачной заливкой. Ничего хитрого здесь не было бы, если бы не странное свойство:
height: Behavior { NumberAnimation { duration: 1000; easing: "InOutQuad" } }
Свойство Behavior указывает нам на поведение объекта при изменении значения height. В данном случае это должна быть анимация. При любом действии, которое устанавливает новое значение высоты, прямоугольник не сразу примет это значение, а лишь выполнив определённую последовательность действий, что очень удобно при создании анимированного гуя.
  BorderImage {
    source: "background.png"
    height: rect.height
    width: rect.width
    border.left: 20
    border.top: 20
    border.bottom: 20
    border.right: 20
  }


* This source code was highlighted with Source Code Highlighter.

В данном блоке демонстрируется создание фонового изображения с обрамлением. И это всё из одной картинки, больше не нужно её разрезать руками, всё будет сделано за вас, нужно лишь указать размеры границ. Думаю многие веб дизайнеры сейчас завидуют.
Чтобы картинка автоматически изменяла свои размеры под размеры прямоугольника, в qml объектах можно использовать property binding, суть его заключается в том, что значение одного параметра привязывается к значению другого и автоматически изменяется при изменении значения оригинального параметра.
Теперь напишем текст
  Text {
    id: title
    text: MyText
    font.pointSize: 14
    wrap: true
    color: "white"

    effect: DropShadow {
     color: "white"
     blurRadius: 2
     offset.x: 0
     offset.y: 0
    }

    anchors.top: rect.top
    anchors.topMargin : 5
    anchors.left: avatar.right
    anchors.leftMargin : 5
  }


* This source code was highlighted with Source Code Highlighter.

Для размещения элементов в qml применяются якоря, в которых указывается положение объекта относительно других объектов, что оказывается весьма удобным. К тексту можно применять различные эффекты, например, эффект тени. Сам текст берётся из контекста, который мы указали ранее. Значение wrap указывает на то, что необходимо делать переносы строк

  Text {    
    id: body
    text: MyObject.text
    font.pointSize: 12
    wrap: true
    color: "white"
    
    //ancors
    anchors.top: title.bottom
    anchors.topMargin: 5
    anchors.right: rect.right
    anchors.rightMargin: 5
    anchors.left: avatar.right
    anchors.leftMargin : 5

    onTextChanged: rect.height = calculateMyHeight();
  }


* This source code was highlighted with Source Code Highlighter.


В этом блоке присутствует слот, который активируется при любом изменении текста, и вызывает javascript функцию, пересчитывающую высоту всего прямоугольника, в котором заключена наша сцена. А текст можно изменять просто вызывая функцию setText у нашего С++ объекта.
  Script {
     function calculateMyHeight() {
       console.log("height : " + (body.y + body.height + 20));
       return (edit.y + edit.height + 20);
  }


* This source code was highlighted with Source Code Highlighter.

В блоке scripts можно описывать javascript'ы, через которые можно взаимодействовать в любыми qml объектами
Оставшийся код можно найти здесь.
В конечном итоге должно получится такое миленькое окошко:

На сегодня всё. С остальными возможностями можно ознакомитmся посмотрев документацию и заглянув в примеры.
PS
Прислали скриншот из Win7, не мог не выложить, для создания размытия используется qtwin


Tags:
Hubs:
+40
Comments 44
Comments Comments 44

Articles