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

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


develop:qt:quick3

Qt Quick: Модель/Представление, Связь с С++

Модель/Представление

В QML предоставляет механизм отделения данных от их представления. За показ отвечают элементы представления и делегаты, а за поставку- элементы моделей.

Модели

Модель - предоставляет интерфейс для обращения к данным, может содержать и сами данные, но не обязательно.

Модель списка

Представлена элементом ListModel и содержит последовательность элементов: ListElement{…} ….
ListElement содержит свойства данных, все они определяются пользователем, стандартных нет.
Элементы можно описывать как вручную, так и динамически, поддерживаются функции типа: append(), insert(), remove(), move и т.д.

:!: Пример: Статическое описание содержимого модели
import QtQuick 2.8
 
ListModel
{
    ListElement
    {
        artist: "Amaranthe"
        album: "Amaranthe"
        year: 2011
        cover: "qrc:/button-press.png"
    }
    ListElement
    {
        artist: "Dark Princess"
        album: "Without"
        year: 2005
        cover: "qrc:/button.png"
    }
    ListElement
    {
        artist: "Within"
        album: "The Unfo"
        year: 2011
        cover: "qrc:/atom.png"
    }
}

 

XML-модель

XmlListModel- тоже модель списка и используется для XML-данных. Задействует для заполнения данными опросы XPath и присваивает данные свойствам.
Для каждого определяемого свойства, определяем XmlRole, что является фактом создания св-ва, задаем ему name, а так же путь откуда извлечь и тип извлекаемых данных.

:!: Пример: Описание Xml-модели
<?xml version = "1.0"?>
<CDs>
	<CD>
		<artist>Amaranthe</artist>
		<album>Amaranthe</album>
		<year>2011</year>
		<cover>qrc:/button-press.png</cover>
	</CD>
	<CD>
		<artist>Dark Princess</artist>
		<album>Without</album>
		<year>2005</year>
		<cover>qrc:/button.png</cover>
	</CD>
	<CD>
		<artist>Within</artist>
		<album>The Unfo</album>
		<year>2011</year>
		<cover>qrc:/atom.png</cover>
	</CD>
</CDs>
import QtQuick 2.8; import QtQuick.XmlListModel 2.0
 
XmlListModel
{
    source: "qrc:/CDs.xml"
    query: "/CDs/CD"
    XmlRole { name: "artist"; query: "artist/string()" }
    XmlRole { name: "album"; query: "album/string()" }
    XmlRole { name: "year"; query: "year/string()" }
    XmlRole { name: "cover"; query: "cover/string()" }
}

 

JSON-модель


Благодаря поддержке JavaScript, данные JSON можно использовать напрямую, например присвоить переменной и далее работать с ней.

:!: Пример: JSON модель
import QtQuick 2.8;
 
var jsonModel = [
    {
        artist: "Amaranthe",
        album: "Amaranthe",
        year: 2011,
        cover: "qrc:/button-press.png",
    },
    {
        artist: "Dark Princess",
        album: "Without",
        year: 2005,
        cover: "qrc:/button.png",
    }
    ,
    {
        artist: "Within",
        album: "The Unfo",
        year: 2011,
        cover: "qrc:/atom.png",
    }
]

 

Представление данных

ListView


Отвечает за отображение данных модели в виде столбца или строки.
За отображение каждого элемента списка в отдельности отвечает делегат.

В примере, в роли делегата реализуем элемент Component, со свойством id, что бы можно было на него сослаться, в блоке Item определяем как будет отображаться каждый элемент нашего списка.
Далее определяем собсна саму модель ListView, в ней ставим focus, для навигации клавиатурой, добавляем header и footer, элемент highlight используется для показа текущего элемента. Так же, присваиваем ей определенные ранее модель и делегат.

:!: Пример: Представление данных из JSON
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
        }
    }
}

 

GridView


GridView автоматически заполняет всю область элементами в табличном порядке, поэтому нет необходимости указывать кол-во строк/столбов.
Использование почти полностью идентично предыдущему примеру, разве что в делегате данные располагаются вертикально.

:!: Пример: Представление данных из JSON
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
        }
    }
}

 

PathView


Показывает элементы в виде замкнутой линии.

Делегат идентичен предыдущим. ключевой момент в создании элемента Path, этот элемент задает форму замкнутой линии, он присваивается свойству path элемента PathView, свойство pathItemCount определяет кол-во одновременно видимых элементов.

:!: Пример: PathView JSON
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
        }
    }
}

Пример прикольной компоновки для предыдущего примера, но работает криво :(

:!: Пример: Вариант компоновки
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 }
}

 

Визуальная модель данных


VisualItemModel - модель которая не нуждается в делегате и сама отвечает за представление своих данных, плюс в том, что каждый элемент может быть отображен в индивидуальной манере.

:!: Пример: Отображение VisualItemModel
// Отдельный файл с данными
import QtQuick 2.12
 
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{}
                }
            }
        }
    }
}

 

Qt Quick и C++

Использование языка QML в C++


В QML интегрирован класс QQuickWidget, который наследуется от QWidget т.е. является обычным виджетом и хорошо подходит для отображения QML-элементов.
Расположен он в модуле quickwidgets, который необходимо добавлять в pro-файл.

:!: Пример: использование QML как виджет в С++

pro-файл содержит: «QT += core gui quick qml quickwidgets».

Файл «myWidget.h»

#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

Файл «myWidget.cpp»

#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()
{
}

Файл элемента QML, main.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
        }
    }
}

 

Взаимодействие из 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.

:!: Пример: Изменение св-в элементов QML и вызов функции, из C++

На основании предыдущего примера, файл myWidget.cpp

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;
        }
    }
}

 

Соединение QML-сигналов со слотами C++


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

В проект добавлены только 2 модуля: «QT += quick qml»

:!: Пример: Соединение сигналов с QML формы со слотами C++ класса

Форма приложения

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()
        }
    }
}

Класс со слотами

#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

Соединение сигналов со слотами, ф-я main

#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();
}

 

Использование компонентов 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 форме.

:!: Пример: Экспорт объектов в QML

Файл класса myWidget.cpp

#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");
}

Форма 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();
        }
    }
}

 

Использование зарегистр объектов C++ в QML


Как я понял, это передача в QML только конкретных свойств и методов, определенных директивами Q_PROPERTY и Q_INVOKABLE соответственно.
Прежде всего производим регистрацию нашего класса, функцией qmlRegisterType<T>(), в нее передается идентификатор модуля (похоже собственный), два параметра с номерами версии, и собсна имя самого класса.

:!: Пример: Передача свойств, методов и сигналов класса в QML

Calculate.h

#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

Calculate.cpp

#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);
}

main.cpp

#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();
}

Два варианта реализации, свойствами и методом

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
            }
        }
    }
}

Альтернативный подход с использованием сигналов

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
        }
    }
}

 

Реализация визуальных элементов QML на C++


Все базовые элементы QML (такие как Rectangle или Text), реализованы на C++ (QQuickRectangle, QQuickText), унаследованы они от QQuickItem, для собственной реализации нужно наследовать этот класс, но есть спец подготовленный для этого- QQuickPaintedItem, он уже унаследован.

:!: Пример: Собственный элемент, эллипс

Ellipse.h

#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

Ellipse.hpp

#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;
}

main.hpp

#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();
}

main.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"
    }
}

 

Класс QQuickImageProvider


Этот класс является неким объектом, который возвращает запрашиваемое изображение (QImage либо QPixmap), запрашивается оно из QML по имени файла (либо какой-нибудь условный идентификатор), зарегистрированный ImageProvider типа папка, а идентификатор имя файла.
Т.к. ImageProvider возвращает (методом request) изображение в как таковом виде (тип данных image/pixmap), его можно всячески модифицировать перед отправкой, или даже вовсе создать в этом методе, либо организовать некую логику, на основании переданных данных например..

:!: Пример: Яркость изображения

ImageProvider.h

#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

ImageProvider.hpp

#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;
}

main.hpp

#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();
}

main.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>"
        }
    }
}
develop/qt/quick3.txt · Последнее изменение: 2021/09/04 10:55 — admin