Инструменты пользователя

Инструменты сайта


develop:qt:quick3

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
develop:qt:quick3 [2021/08/30 14:02]
admin
develop:qt:quick3 [2021/09/04 10:55] (текущий)
admin
Строка 9: Строка 9:
  
 === Модель списка === === Модель списка ===
----- 
 Представлена элементом **ListModel** и содержит последовательность элементов: **ListElement{...} ...**.\\ Представлена элементом **ListModel** и содержит последовательность элементов: **ListElement{...} ...**.\\
 **ListElement** содержит свойства данных, все они **определяются пользователем**, стандартных нет.\\ **ListElement** содержит свойства данных, все они **определяются пользователем**, стандартных нет.\\
Строка 46: Строка 45:
 </details> </details>
  
 + 
 === XML-модель === === XML-модель ===
----- 
 **XmlListModel**- тоже модель списка и используется для XML-данных. Задействует для заполнения данными опросы **XPath** и присваивает данные свойствам.\\ **XmlListModel**- тоже модель списка и используется для XML-данных. Задействует для заполнения данными опросы **XPath** и присваивает данные свойствам.\\
 Для каждого определяемого свойства, определяем **XmlRole**, что является фактом создания св-ва, задаем ему **name**, а так же путь откуда извлечь и тип извлекаемых данных.\\ Для каждого определяемого свойства, определяем **XmlRole**, что является фактом создания св-ва, задаем ему **name**, а так же путь откуда извлечь и тип извлекаемых данных.\\
Строка 93: Строка 91:
 </details> </details>
  
 + 
 === JSON-модель === === JSON-модель ===
 ---- ----
Строка 127: Строка 125:
 </details> </details>
  
 + 
 ==== Представление данных ==== ==== Представление данных ====
 === ListView === === ListView ===
Строка 140: Строка 138:
 <summary>:!: Пример: Представление данных из JSON</summary> <summary>:!: Пример: Представление данных из JSON</summary>
 <code QML> <code QML>
 +import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Particles 2.0
 +import "qrc:/CDs.js" as CDs
  
 +ApplicationWindow
 +{
 +    width: 200; height: 360; visible: true
 +    Rectangle
 +    {
 +        id: mainrect
 +        anchors.fill: parent
 +        color: "gray"
 +        Component
 +        {
 +            id: delegate
 +            Item
 +            {
 +                width: mainrect.width; height: 70
 +                Row
 +                {
 +                    anchors.verticalCenter: parent.verticalCenter
 +                    Image
 +                    {
 +                        width: 64; height: 64
 +                        source: modelData.cover
 +                        smooth: true
 +                    }
 +                    Column
 +                    {
 +                        Text
 +                        {
 +                            color: "white"
 +                            text: modelData.artist
 +                            font.pointSize: 12
 +                        }
 +                        Text
 +                        {
 +                            color: "lightblue"
 +                            text: modelData.album
 +                            font.pointSize: 10
 +                        }
 +                        Text
 +                        {
 +                            color: "yellow"
 +                            text: modelData.year
 +                            font.pointSize: 8
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +        ListView
 +        {
 +            focus: true
 +            header: Rectangle
 +            {
 +                width: parent.width; height: 30
 +                gradient: Gradient
 +                {
 +                    GradientStop { position: 0; color: "gray" }
 +                    GradientStop { position: 0.7; color: "black" }
 +                }
 +                Text
 +                {
 +                    anchors.centerIn: parent
 +                    color: "gray"; text: "CDs"
 +                    font.bold: true; font.pointSize: 20
 +                }
 +            }
 +            footer: Rectangle
 +            {
 +                width: parent.width; height: 30
 +                gradient: Gradient
 +                {
 +                    GradientStop { position: 0; color: "gray" }
 +                    GradientStop { position: 0.7; color: "black" }
 +                }
 +            }
 +            highlight: Rectangle
 +            {
 +                width: parent.width
 +                color: "darkblue"
 +            }
 +            anchors.fill: parent
 +            model: CDs.jsonModel
 +            delegate: delegate
 +        }
 +    }
 +}
 </code> </code>
 </details> </details>
  
 + 
 +=== GridView ===
 +----
 +**GridView** автоматически заполняет всю область элементами в табличном порядке, поэтому нет необходимости указывать кол-во строк/столбов.\\
 +Использование почти полностью идентично предыдущему примеру, разве что в делегате данные располагаются вертикально.\\
  
 +<details>
 +<summary>:!: Пример: Представление данных из JSON</summary>
 +<code QML>
 +import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Particles 2.0
 +import "qrc:/CDs.js" as CDs
  
 +ApplicationWindow
 +{
 +    width: 380; height: 420; visible: true
 +    Rectangle
 +    {
 +        id: mainrect
 +        anchors.fill: parent
 +        color: "gray"
 +        Component
 +        {
 +            id: delegate
 +            Item
 +            {
 +                width: 120; height: 120
 +                Column
 +                {
 +                    anchors.centerIn: parent
 +                    Image
 +                    {
 +                        anchors.horizontalCenter: parent.horizontalCenter
 +                        width: 64; height: 64
 +                        source: modelData.cover
 +                        smooth: true
 +                    }
 +                    Text
 +                    {
 +                        color: "white"; text: modelData.artist; font.pointSize: 12
 +                    }
 +                    Text
 +                    {
 +                        color: "lightblue"; text: modelData.album; font.pointSize: 10
 +                    }
 +                    Text
 +                    {
 +                        color: "yellow"; text: modelData.year; font.pointSize: 8
 +                    }
 +                }
 +            }
 +        }
 +        GridView
 +        {
 +            cellWidth: 120; cellHeight: 120
 +            focus: true
 +            header: Rectangle
 +            {
 +                width: parent.width; height: 30
 +                gradient: Gradient
 +                {
 +                    GradientStop { position: 0; color: "gray" }
 +                    GradientStop { position: 0.7; color: "black" }
 +                }
 +                Text
 +                {
 +                    anchors.centerIn: parent
 +                    color: "gray"; text: "CDs"
 +                    font.bold: true; font.pointSize: 20
 +                }
 +            }
 +            footer: Rectangle
 +            {
 +                width: parent.width; height: 30
 +                gradient: Gradient
 +                {
 +                    GradientStop { position: 0; color: "gray" }
 +                    GradientStop { position: 0.7; color: "black" }
 +                }
 +            }
 +            highlight: Rectangle
 +            {
 +                width: parent.width
 +                color: "darkblue"
 +            }
 +            anchors.fill: parent
 +            model: CDs.jsonModel
 +            delegate: delegate
 +        }
 +    }
 +}
 +</code>
 +</details>
  
-=== GridView ===+  
 +=== PathView ===
 ---- ----
 +Показывает элементы в виде замкнутой линии.\\
  
 +Делегат идентичен предыдущим. ключевой момент в создании элемента **Path**, этот элемент задает форму замкнутой линии, он присваивается свойству **path** элемента **PathView**, свойство **pathItemCount** определяет кол-во одновременно видимых элементов.\\
  
 <details> <details>
-<summary>:!: Пример: </summary>+<summary>:!: Пример: PathView JSON</summary>
 <code QML> <code QML>
 +import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Particles 2.0
 +import "qrc:/CDs.js" as CDs
  
 +ApplicationWindow
 +{
 +    width: 450; height: 170; visible: true
 +    Rectangle
 +    {
 +        anchors.fill: parent
 +        color: "gray"
 +        Component
 +        {
 +            id: delegate
 +            Item
 +            {
 +                width: item.width; height: item.height
 +                Column
 +                {
 +                    id: item
 +                    Image
 +                    {
 +                        width: 90; height: 90
 +                        source: modelData.cover
 +                        smooth: true
 +                    }
 +                    Text
 +                    {
 +                        color: "white"; text: modelData.artist; font.pointSize: 12
 +                    }
 +                    Text
 +                    {
 +                        color: "lightblue"; text: modelData.album; font.pointSize: 10
 +                    }
 +                    Text
 +                    {
 +                        color: "yellow"; text: modelData.year; font.pointSize: 8
 +                    }
 +                }
 +            }
 +        }
 +        Path
 +        {
 +            id: itemsPath
 +            startX: 45; startY: 80 // Не совсем понятны эти значения
 +            PathLine {x: 500; y: 80} // И эти тоже
 +        }
 +        PathView
 +        {
 +            id: itemsView
 +            focus: true
 +            anchors.fill: parent
 +            model: CDs.jsonModel
 +            delegate: delegate
 +            path: itemsPath
 +            pathItemCount: 4
 +        }
 +    }
 +}
 </code> </code>
 </details> </details>
  
 +Пример прикольной компоновки для предыдущего примера, но работает криво :(
 +<details>
 +<summary>:!: Пример: Вариант компоновки</summary>
 +<code QML>
 +Path
 +{
 +    id: itemsPath
 +    startX: 150; startY: 150
 +    PathAttribute { name: "iconScale"; value: 1.0 }
 +    PathAttribute { name: "iconOpacity"; value: 1.0 }
 +    PathQuad { x: 150; y: 25; controlX: 460; controlY: 75 }
 +    PathAttribute { name: "iconScale"; value: 0.3 }
 +    PathAttribute { name: "iconOpacity"; value: 0.3 }
 +    PathQuad { x: 150; y: 150; controlX: -80; controlY: 75 }
 +}
 +</code>
 +</details>
  
 + 
 +==== Визуальная модель данных ====
 +----
 +**VisualItemModel** - модель которая не нуждается в делегате и сама отвечает за представление своих данных, плюс в том, что каждый элемент может быть **отображен в индивидуальной манере**.\\
  
 +<details>
 +<summary>:!: Пример: Отображение VisualItemModel</summary>
 +<code QML>
 +// Отдельный файл с данными
 +import QtQuick 2.12
  
-=== PathView === +VisualItemModel 
-----+
 +    Row 
 +    { 
 +        Image 
 +        { 
 +            width: 64; height: 64 
 +            source: "qrc:/button.png" 
 +            smooth: true 
 +        } 
 +        Column 
 +        { 
 +            Text { color: "white"; text: "111"; font.pointSize: 12 } 
 +            Text { color: "lightblue"; text: "112"; font.pointSize: 10 } 
 +            Text { color: "yellow"; text: "113"; font.pointSize: 8 } 
 +        } 
 +    } 
 +    Rectangle 
 +    { 
 +        width: parent.width; height: 64 
 +        color: "yellow" 
 +        Text 
 +        { 
 +            anchors.centerIn: parent 
 +            color: "red" 
 +            text: "Blank" 
 +        } 
 +    } 
 +    Row 
 +    { 
 +        Image 
 +        { 
 +            width: 64; height: 64 
 +            source: "qrc:/button-press.png" 
 +            smooth: true 
 +        } 
 +        Column 
 +        { 
 +            Text { color: "white"; text: "221"; font.pointSize: 12 } 
 +            Text { color: "lightblue"; text: "222"; font.pointSize: 10 } 
 +            Text { color: "yellow"; text: "223"; font.pointSize: 8 } 
 +        } 
 +    }
  
 +}
 +
 +// Основной файл программы
 +import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Particles 2.0
 +import "qrc:/CDs.js" as CDs
 +
 +ApplicationWindow
 +{
 +    width: 250; height: 250; visible: true
 +    Rectangle
 +    {
 +        anchors.fill: parent
 +        color: "DarkSlateGray"
 +        Flickable
 +        {
 +            id: view
 +            width: 250; height: 500
 +            contentWidth: 250; contentHeight: column.height
 +            anchors.fill: parent
 +            Column
 +            {
 +                id: column
 +                anchors.fill: view
 +                spacing: 5
 +                Repeater
 +                {
 +                    model: CDs{}
 +                }
 +            }
 +        }
 +    }
 +}
 +</code>
 +</details>
 +
 + 
 +===== Qt Quick и C++ =====
 +==== Использование языка QML в C++ ====
 +----
 +В QML интегрирован класс **QQuickWidget**, который наследуется от **QWidget** т.е. является обычным виджетом и хорошо подходит для отображения QML-элементов.\\
 +Расположен он в модуле **quickwidgets**, который необходимо добавлять в **pro-файл**.\\
  
 <details> <details>
-<summary>:!: Пример: </summary>+<summary>:!: Пример: использование QML как виджет в С++</summary> 
 + 
 +**pro-файл** содержит: "QT += core gui quick qml quickwidgets".\\ 
 + 
 +Файл **"myWidget.h"** 
 +<code cpp-qt> 
 +#ifndef MYWIDGET_H 
 +#define MYWIDGET_H 
 + 
 +#include <QWidget> 
 +#include <QQuickWidget> 
 +#include <QVBoxLayout> 
 + 
 +class MyWidget : public QWidget 
 +
 +    Q_OBJECT 
 + 
 +public: 
 +    MyWidget(QWidget *parent = nullptr); 
 +    ~MyWidget(); 
 +}; 
 +#endif // MYWIDGET_H 
 +</code> 
 + 
 + 
 +Файл **"myWidget.cpp"** 
 +<code cpp-qt> 
 +#include "mywidget.h" 
 + 
 +MyWidget::MyWidget(QWidget *parent): QWidget(parent) 
 +
 +    QQuickWidget* pv= new QQuickWidget(QUrl("qrc:/main.qml")); 
 +    QVBoxLayout* pvbox= new QVBoxLayout; 
 +    pvbox->addWidget(pv); 
 +    setLayout(pvbox); 
 +
 + 
 +MyWidget::~MyWidget() 
 +
 +
 +</code> 
 + 
 + 
 +Файл элемента QML, **main.qml**, добавленный в ресурсы
 <code QML> <code QML>
 +import QtQuick 2.0
  
 +Rectangle
 +{
 +    color: "lightgreen"
 +    width: 100; height: 100
 +    Text
 +    {
 +        objectName: "text"
 +        anchors.centerIn: parent
 +        text: "Hello QML"
 +        
 +        function setFontSize(newSize)
 +        {
 +            font.pixelSize= newSize
 +            return font.family + " Size= "+ newSize
 +        }
 +    }
 +}
 </code> </code>
 </details> </details>
  
 + 
 +=== Взаимодействие из C++ со св-вами элементов QML ===
 +----
 +Базовый QML элемент **Item** реализован в C++ классом **QQuickItem**, который унаследован от **QObject**, наравне с QWidget.\\
 +Через свойство **objectName**, указанное в QML, можно получить доступ к объекту класса **QQuickItem** и с ним можно работать как с обычным объектом **QObject**.\\
  
 +В следующем примере (на базе предыдущего), с помощью вызова **QQuickWidget::rootObject()** мы получаем указатель на узловой объект **QQuickItem** (в данном случае это Rectangle).\\
 +Далее у этого объекта, с помощью методов **setProperty()** устанавливаем/изменяем нужные свойства.\\
 +С помощью метода **findChild()** мы можем получить указатели на дочерние элементы, и так же доступ к их свойствам.\\
  
-==== Визуальная модель данных ==== +Затем вызываем пользовательскую JavaScript функцию из **QML**:\\ 
-----+Все функции в QML представлены в метаобъектной информации, благодаря этом могут быть вызваны из C++, с помощью метода **QMetaObject::invokeMethod()**.\\ 
 +В этот метод мы передаем указатель на объект, содержащий ф-ю, затем имя функ-ции, в макросе **Q_RETURN_ARG** передается переменная для результата, последними передаются макросы с аргументами- **Q_ARG**, равное кол-ву принимаемых аргументов. Тип данных используется **QVariant**.\\ 
  
 +<details>
 +<summary>:!: Пример: Изменение св-в элементов QML и вызов функции, из C++</summary>
 +На основании предыдущего примера, файл **myWidget.cpp**
 +<code cpp-qt>
 +MyWidget::MyWidget(QWidget *parent): QWidget(parent)
 +{
 +    QQuickWidget* pv= new QQuickWidget(QUrl("qrc:/main.qml"));
 +    QVBoxLayout* pvbox= new QVBoxLayout;
 +    pvbox->addWidget(pv);
 +    setLayout(pvbox);
 +
 +    QQuickItem *pqiRoot= pv->rootObject();
 +    if(pqiRoot)
 +    {
 +        pqiRoot->setProperty("color", "yellow");
 +        QObject *pObjText= pqiRoot->findChild<QObject*>("text");
 +        if(pObjText)
 +        {
 +            pObjText->setProperty("text", "C++");
 +            pObjText->setProperty("color", "blue");
 +            QVariant varRet;
 +            QMetaObject::invokeMethod(pObjText, "setFontSize", Q_RETURN_ARG(QVariant, varRet), Q_ARG(QVariant, 52));
 +            qDebug() << varRet;
 +        }
 +    }
 +}
 +</code>
 +</details>
 +
 + 
 +=== Соединение QML-сигналов со слотами C++ ===
 +----
 +В прошлых примерах мы использовали QML внутри виджетов, теперь мы исключим их и уберем лишние зависимости.\\
 +На этот раз вся **форма** будет **QML**, на **C++** реализованы **действия** по нажатию кнопок.\\
  
 +В проект добавлены только 2 модуля: **"QT += quick qml"**
 <details> <details>
-<summary>:!: Пример: </summary>+<summary>:!: Пример: Соединение сигналов с QML формы со слотами C++ класса</summary> 
 +**Форма приложения**
 <code QML> <code QML>
 +import QtQuick 2.8; import QtQuick.Controls 2.2; import QtQuick.Window 2.2
  
 +ApplicationWindow
 +{
 +    visible: true
 +    width: 150; height: 150;
 +    Column
 +    {
 +        anchors.centerIn: parent
 +        spacing: 5
 +        Button
 +        {
 +            signal infoClick(string str)
 +            objectName: "InfoButton"
 +            text: "Info"
 +            onClicked: infoClick("Information")
 +        }
 +        Button
 +        {
 +            signal quitClick()
 +            objectName: "QuitButton"
 +            text: "Quit"
 +            onClicked: quitClick()
 +        }
 +    }
 +}
 </code> </code>
-</details> 
  
 +**Класс со слотами**
 +<code cpp-qt>
 +#ifndef MYWIDGET_H
 +#define MYWIDGET_H
  
 +#include <QtCore>
  
 +class CppConnect : public QObject
 +{
 +    Q_OBJECT
 +
 +public:
 +    CppConnect(QObject *parent = nullptr)
 +    {
 +    }
 +
 +public slots:
 +    void slotQuit()
 +    {
 +        qApp->quit();
 +    }
 +
 +    void slotInfo(const QString str)
 +    {
 +        qDebug() << str;
 +    }
 +
 +};
 +#endif // MYWIDGET_H
 +</code>
 +
 +**Соединение сигналов со слотами, ф-я main**
 +<code cpp-qt>
 +#include <QGuiApplication>
 +#include <QQmlApplicationEngine>
 +#include <QQmlComponent>
 +#include "mywidget.h"
 +
 +int main(int argc, char** argv)
 +{
 +    QGuiApplication app(argc, argv);
 +    QQmlApplicationEngine eng;
 +    QQmlComponent comp(&eng, QUrl("qrc:/main.qml"));
 +    CppConnect cc;
 +    QObject *pobj= comp.create();
 +
 +    QObject *pcmdQuitButton= pobj->findChild<QObject*>("QuitButton");
 +    if(pcmdQuitButton)
 +    {
 +        QObject::connect(pcmdQuitButton, SIGNAL(quitClick()), &cc, SLOT(slotQuit()));
 +    }
 +
 +    QObject *pcmdInfoButton= pobj->findChild<QObject*>("InfoButton");
 +    if(pcmdInfoButton)
 +    {
 +        QObject::connect(pcmdInfoButton, SIGNAL(infoClick(QString)), &cc, SLOT(slotInfo(QString)));
 +    }
 +    return app.exec();
 +}
 +</code>
 +</details>
  
-====  ====+  
 +==== Использование компонентов C++ в QML ====
 ---- ----
 +В QML реализована возможность расширения при помощи C++, благодаря этому можно QML расширять новыми элементами из C++.\\
 +Существующие технологии импортируются директивой **import**, например "import QtWebEngine 1.5".\\
  
 +Работа происходит через класс контекста **QQmlContext**, что бы получить доступ к объекту этого класса, нужно из объекта класса **QQuickWidget** вызвать метод **rootContext()**, который вернет указатель на корневой контекст.\\
 +Используя этот указатель вы можете ввести в дерево контекста новые объекты классов, унаследованных от **QObject**. Публикация происходит с помощью метода **setContextProperty()**, он принимает имя объекта и собсна адрес самого объекта.\\
 +После этого, свойства класса **QObject** станут свойствами QML, а слоты и методы (декларированные с Q_INVOKABLE) смогут вызываться из вашего QML-элемента.\\
 +Класс **QQuickWidget** так же содержит объект класса **QQmlEngine** (вызов engine()), который предоставляет среду для исполнения QML.\\
 +
 + 
 +=== Экспорт объектов и виджетов из C++ в QML ===
 +----
 +Пример экспорта, создаем C++ класс, в конструкторе делаем загрузку и отображение QML формы, виджетом и создаем несколько локальных объектов, которые экспортируются в QML форму, так же экспортируется и объект самого класса (this), определяем слот, все это будет **доступно в QML форме**.\\
  
 <details> <details>
-<summary>:!: Пример: </summary>+<summary>:!: Пример: Экспорт объектов в QML</summary> 
 +**Файл класса myWidget.cpp** 
 +<code cpp-qt> 
 +#include "mywidget.h" 
 + 
 +MyWidget::MyWidget(QWidget *parent): QWidget(parent) 
 +
 +    QQuickWidget *pv= new QQuickWidget(this); 
 +    pv->setSource(QUrl("qrc:/main.qml")); 
 + 
 +    QVBoxLayout *pvbx= new QVBoxLayout(this); 
 +    pvbx->addWidget(pv); 
 +    setLayout(pvbx); 
 + 
 +    QQmlContext *pcon= pv->rootContext(); 
 +    QStringList lst; 
 +    for(int i= 0; i < 100; i++) 
 +        lst << "Item"+ QString::number(i); 
 +    QStringListModel *pmodel= new QStringListModel(this); 
 +    pmodel->setStringList(lst); 
 + 
 +    pcon->setContextProperty("myModel", pmodel); 
 +    pcon->setContextProperty("myText", "It's my text"); 
 +    pcon->setContextProperty("myColor", QColor(Qt::yellow)); 
 +    pcon->setContextProperty("myWidget", this); 
 +
 + 
 +void MyWidget::slotDisplayDialog() 
 +
 +    QMessageBox::information(0, "Title Message", "Text in message"); 
 +
 +</code> 
 + 
 + 
 +**Форма QML**
 <code QML> <code QML>
 +import QtQuick 2.8
  
 +Rectangle
 +{
 +    width: 200; height: 200;
 +    color: myColor
 +    Text
 +    {
 +        anchors.centerIn: parent
 +        text: myText
 +    }
 +    ListView
 +    {
 +        anchors.fill: parent
 +        model: myModel
 +        delegate: Text { text: model.display }
 +    }
 +    MouseArea
 +    {
 +        anchors.fill: parent
 +        onPressed:
 +        {
 +            myWidget.setWindowTitle("Hello from QML");
 +            myWidget.slotDisplayDialog();
 +        }
 +    }
 +}
 </code> </code>
 </details> </details>
  
 + 
 +=== Использование зарегистр объектов C++ в QML ===
 +----
 +Как я понял, это передача в QML только **конкретных свойств и методов**, определенных директивами **Q_PROPERTY** и **Q_INVOKABLE** соответственно.\\
 +Прежде всего производим регистрацию нашего класса, функцией **qmlRegisterType<T>()**, в нее передается идентификатор модуля (похоже собственный), два параметра с номерами версии, и собсна имя самого класса.\\
  
 +<details>
 +<summary>:!: Пример: Передача свойств, методов и сигналов класса в QML</summary>
 +**Calculate.h**
 +<code cpp-qt>
 +#ifndef CALCULATION_H
 +#define CALCULATION_H
  
-====  ==== +#include <QObject>
-----+
  
 +class Calculation : public QObject
 +{
 +    Q_OBJECT
 +private:
 +    Q_PROPERTY(qulonglong input WRITE setInputValue
 +                                READ inputValue
 +                                NOTIFY inputValueChanged) // Уведомление об изменении
 +    Q_PROPERTY(qulonglong result READ resultValue
 +                                 NOTIFY inputValueChanged)
 +    qulonglong m_nInput;
 +    qulonglong m_nResult;
 +
 +public:
 +    explicit Calculation(QObject *parent = nullptr);
 +
 +    Q_INVOKABLE qulonglong factorial(const qulonglong &n);
 +    qulonglong inputValue() const;
 +    void setInputValue(const qulonglong&);
 +    qulonglong resultValue() const;
 +
 +signals:
 +    void inputValueChanged(qulonglong);
 +    void resultValueChanged(qulonglong);
 +};
 +
 +#endif // CALCULATION_H
 +</code>
 +
 +
 +**Calculate.cpp**
 +<code cpp-qt>
 +#include "calculation.h"
 +
 +Calculation::Calculation(QObject *parent) : QObject(parent), m_nInput(0), m_nResult(1)
 +{
 +}
 +
 +qulonglong Calculation::factorial(const qulonglong &n)
 +{
 +    return n ? (n * factorial(n-1)) : 1;
 +}
 +
 +qulonglong Calculation::inputValue() const
 +{
 +    return m_nInput;
 +}
 +
 +qulonglong Calculation::resultValue() const
 +{
 +    return m_nResult;
 +}
 +
 +void Calculation::setInputValue(const qulonglong &n)
 +{
 +    m_nInput= n;
 +    m_nResult= factorial(m_nInput);
 +    emit inputValueChanged(m_nInput);
 +    emit resultValueChanged(m_nResult);
 +}
 +</code>
 +
 +**main.cpp**
 +<code cpp-qt>
 +#include <QGuiApplication>
 +#include <QQmlApplicationEngine>
 +#include "calculation.h"
 +
 +int main(int argc, char** argv)
 +{
 +    QGuiApplication app(argc, argv);
 +    qmlRegisterType<Calculation>("my.class.Calc", 1, 0, "Calculatoin");
 +    QQmlApplicationEngine engine;
 +    engine.load(QUrl("qrc:/main.qml"));
 +
 +    return app.exec();
 +}
 +</code>
 +
 +
 +**Два варианта** реализации, свойствами и методом
 +<code QML>
 +import QtQuick 2.8; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.3;
 +import my.class.Calc 1.0
 +
 +ApplicationWindow
 +{
 +    title: "Factorial Calc"; width: 250; height: 80;
 +    visible: true
 +    Calculation
 +    {
 +        id: calc
 +    }
 +    ColumnLayout
 +    {
 +        anchors.fill: parent
 +        RowLayout // Первый подход, с использованием метода
 +        {
 +            SpinBox
 +            {
 +                id: sbx
 +                value: 0
 +            }
 +            Text
 +            {
 +                text: "Result: "+ calc.factorial(sbx.value)
 +            }
 +        }
 +        RowLayout // Второй подход, с использованием свойств
 +        {
 +            SpinBox
 +            {
 +                value: 0
 +                onValueChanged: calc.input= value
 +            }
 +            Text
 +            {
 +                text: "Result: "+ calc.result
 +            }
 +        }
 +    }
 +}
 +</code>
 +
 +
 +**Альтернативный подход** с использованием сигналов
 +<code QML>
 +import QtQuick 2.8; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.3;
 +import my.class.Calc 1.0
 +
 +ApplicationWindow
 +{
 +    title: "Factorial Calc"; width: 250; height: 80;
 +    visible: true
 +    Calculatoin
 +    {
 +        input: sbx.value
 +        onResultValueChanged: txt.text= "Result: "+ result
 +    }
 +    RowLayout
 +    {
 +        SpinBox
 +        {
 +            id: sbx
 +            value: 0
 +        }
 +        Text
 +        {
 +            id: txt
 +        }
 +    }
 +}
 +</code>
 +</details>
 +
 + 
 +=== Реализация визуальных элементов QML на C++ ===
 +----
 +Все базовые **элементы QML** (такие как Rectangle или Text), **реализованы на C++** (QQuickRectangle, QQuickText), унаследованы они от **QQuickItem**, для собственной реализации нужно наследовать этот класс, но есть спец подготовленный для этого- **QQuickPaintedItem**, он уже унаследован.\\
  
 <details> <details>
-<summary>:!: Пример: </summary>+<summary>:!: Пример: Собственный элемент, эллипс</summary> 
 +**Ellipse.h** 
 +<code cpp-qt> 
 +#ifndef ELLIPSE_H 
 +#define ELLIPSE_H 
 + 
 +#include <QQuickPaintedItem> 
 + 
 +class QPainter; 
 + 
 +class Ellipse: public QQuickPaintedItem 
 +
 +    Q_OBJECT 
 + 
 +private: 
 +    Q_PROPERTY(QColor color WRITE setColorValue 
 +                            READ colorValue) 
 +    QColor m_color; 
 + 
 +public: 
 +    Ellipse(QQuickItem *parent= nullptr); 
 +    // Отвечает рисование элемента, вызывается при обновлении 
 +    void paint(QPainter *ppainter); 
 +    QColor colorValue() const; 
 +    void setColorValue(const QColor&); 
 +}; 
 + 
 +#endif // ELLIPSE_H 
 +</code> 
 + 
 + 
 +**Ellipse.hpp** 
 +<code cpp-qt> 
 +#include "ellipse.h" 
 +#include <QPainter> 
 + 
 +Ellipse::Ellipse(QQuickItem *parent): QQuickPaintedItem(parent), m_color(Qt::black) 
 +
 +
 + 
 +void Ellipse::paint(QPainter *ppainter) 
 +
 +    ppainter->setRenderHint(QPainter::Antialiasing, true); 
 +    ppainter->setBrush(QBrush(this->colorValue())); 
 +    ppainter->setPen(Qt::NoPen); 
 +    ppainter->drawEllipse(boundingRect()); 
 +
 + 
 +QColor Ellipse::colorValue() const 
 +
 +    return this->m_color; 
 +
 + 
 +void Ellipse::setColorValue(const QColor &vCol) 
 +
 +    this->m_color= vCol; 
 +
 +</code> 
 + 
 + 
 +**main.hpp** 
 +<code cpp-qt> 
 +#include <QGuiApplication> 
 +#include <QQmlApplicationEngine> 
 +#include "ellipse.h" 
 + 
 +int main(int argc, char** argv) 
 +
 +    QGuiApplication app(argc, argv); 
 +    qmlRegisterType<Ellipse>("my.class.Ellipse", 1, 0, "Ellipse"); 
 +    QQmlApplicationEngine engine; 
 +    engine.load(QUrl("qrc:/main.qml")); 
 + 
 +    return app.exec(); 
 +
 +</code> 
 + 
 + 
 +**main.qml**
 <code QML> <code QML>
 +import QtQuick 2.8; import QtQuick.Controls 2.2
 +import my.class.Ellipse 1.0
  
 +ApplicationWindow
 +{
 +    title: "Paint Element"; width: 200; height: 100;
 +    visible: true
 +    Ellipse
 +    {
 +        anchors.fill: parent
 +        color: "blue"
 +    }
 +}
 </code> </code>
 </details> </details>
  
 + 
 +=== Класс QQuickImageProvider ====
 +----
 +Этот класс является неким объектом, который возвращает запрашиваемое изображение (QImage либо QPixmap), запрашивается оно из QML по имени файла (либо какой-нибудь условный идентификатор), зарегистрированный ImageProvider типа папка, а идентификатор имя файла.\\
 +Т.к. ImageProvider возвращает (методом request) изображение в как таковом виде (тип данных image/pixmap), его можно всячески модифицировать перед отправкой, или даже вовсе создать в этом методе, либо организовать некую логику, на основании переданных данных например..\\
 +
 +<details>
 +<summary>:!: Пример: Яркость изображения</summary>
 +
 +**ImageProvider.h**
 +<code cpp-qt>
 +#ifndef IMAGEPROVIDER_H
 +#define IMAGEPROVIDER_H
 +#include <QQuickImageProvider>
 +#include <QObject>
 +#include <QImage>
 +
 +class ImageProvider: public QQuickImageProvider
 +{
 +private:
 +    QImage brightness(const QImage &imgOrig, int n);
 +
 +public:
 +    ImageProvider();
 +    QImage requestImage(const QString&, QSize*, const QSize&);
 +};
 +
 +#endif // IMAGEPROVIDER_H
 +</code>
 +
 +
 +**ImageProvider.hpp**
 +<code cpp-qt>
 +#include "imageprovider.h"
 +
 +ImageProvider::ImageProvider(): QQuickImageProvider(QQuickImageProvider::Image)
 +{
 +}
 +
 +QImage ImageProvider::brightness(const QImage &imgOrig, int n)
 +{
 +    QImage imgTemp= imgOrig;
 +    qint32 nHeigt= imgTemp.height();
 +    qint32 nWidth= imgTemp.width();
 +
 +    for(qint32 y= 0; y < nHeigt; ++y)
 +    {
 +        QRgb *tempLine= reinterpret_cast<QRgb*>(imgTemp.scanLine(y));
 +        for(qint32 x= 0; x < nWidth; ++x)
 +        {
 +            int r= qRed(*tempLine) + n;
 +            int g= qGreen(*tempLine) + n;
 +            int b= qBlue(*tempLine) + n;
 +            int a= qAlpha(*tempLine);
 +
 +            *tempLine++ = qRgba(r > 255 ? 255 : r < 0 ? 0:r,
 +                                g > 255 ? 255 : g < 0 ? 0:g,
 +                                b > 255 ? 255 : b < 0 ? 0:b,
 +                                a);
 +        }
 +    }
 +    return imgTemp;
 +}
 +
 +QImage ImageProvider::requestImage(const QString &strId, QSize *ps, const QSize &requestedSize)
 +{
 +    QStringList lst= strId.split(";");
 +    bool bOk= false;
 +    int nBrightness= lst.last().toInt(&bOk);
 +    QImage img= brightness(QImage(":/"+ lst.first()), nBrightness);
 +
 +    if(ps)
 +        *ps= img.size();
 +
 +    return img;
 +}
 +</code>
 +
 +
 +**main.hpp**
 +<code cpp-qt>
 +#include <QGuiApplication>
 +#include <QQmlApplicationEngine>
 +#include "imageprovider.h"
 +
 +int main(int argc, char** argv)
 +{
 +    QGuiApplication app(argc, argv);
 +    QQmlApplicationEngine engine;
 +    engine.addImageProvider(QLatin1String("brightness"), new ImageProvider);
 +    engine.load(QUrl("qrc:/main.qml"));
 +
 +    return app.exec();
 +}
 +</code>
 +
 +
 +**main.qml**
 +<code QML>
 +import QtQuick 2.8; import QtQuick.Controls 2.2
 +
 +ApplicationWindow
 +{
 +    title: "Brightness"; width: controls.width; height: controls.height;
 +    visible: true
 +    Column
 +    {
 +        id: controls
 +        Image
 +        {
 +            id: img
 +            source: "image://brightness/11.jpg;"+ sld.brightnessValue
 +        }
 +        Slider
 +        {
 +            id: sld
 +            width: img.width
 +            value: 0.75
 +            stepSize: 0.01
 +            property int brightnessValue: (value * 255 -127)
 +        }
 +        Text
 +        {
 +            width: img.width
 +            text: "<h1>Brightness: "+ sld.brightnessValue+ "</h1>"
 +        }
 +    }
 +}
 +</code>
 +</details>
develop/qt/quick3.1630332122.txt.gz · Последнее изменение: 2021/08/30 14:02 — admin