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

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


develop:qt:quick2

Это старая версия документа!


Qt Quick: Ввод, Анимация, Преставление, С++

Элементы графики

Растровые изображения

Можно использовать форматы: JPG, PNG и SVG.

Элемент Image

Этот элемент отображает файл изображения, указанный в свойстве source, файл может находится как локально так и в сети.
Есть интерактивный редактор для изменения свойств.
Свойствами можно подвергать изображение трансформациям, типа увеличение/уменьшение (scale), поворот (rotation), сглаживание (smooth).

:!: Пример: Изображение с уменьшением, поворотом и сглаживанием
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: img.width; height: img.height; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Image
        {
            id: img
            source: "qrc:/../../../../Downloads/11.jpg"
            x: 0; y: 0
            smooth: true
            scale:  0.75
            rotation: -30
        }
    }
}

Для более тонкой настройки трансформации, ее можно задавать списками (в квадратных скобках).

:!: Пример: Аналогично, только трансформацию задаем двумя списками свойству transform
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: img.width; height: img.height; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Image
        {
            id: img
            source: "qrc:/../../../../Downloads/11.jpg"
            x: 0; y: 0
            smooth: true
            transform:
            [
                Scale
                {
                    origin.x: width / 2
                    origin.y: width / 2
                    xScale: 0.75
                    yScale: 0.75
                },
                Rotation
                {
                    origin.x: width / 2
                    origin.y: width / 2
                    angle: -30.0
                }
            ]
        }
    }
}

Добавим элемент загрузки BusyIndicator

:!: Пример: Загрузка и отображение изображения из web
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: 640; height: 480; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Image
        {
            id: img
            source: "http://qt-book.com/pic.jpg"
            anchors.fill: parent
            smooth: true
            Column
            {
                anchors.centerIn: parent
                visible: img.status == Image.Loading ? true:false
                Text
                {
                    text: "Загрузка..."
                }
                BusyIndicator
                {}
            }
        }
    }
}

BorderImage


Элемент для нормального масштабирования графики, особенно полезно при закругленных углах (кнопок и т.д.). Элемент разбивает изображение на девять частей.

:!: Пример: Масштабируемое изображение кнопки, с закругленными углами
import QtQuick 2.12
 
BorderImage
{
    source: ""
    width: 100; height: 45
    border {left: 30; top: 15; right: 30; bottom: 15}
}

Градиент


В QML есть только один градиент - линейный, если нужен другой, можно воспользоваться трансформацией.
Для создания, нужно свойству gradient присвоить элемент Gradient, он содержит точки останова (GradientStop) с позициями от 0 до 1.

Создание градиентов может потребовать много ресурсов, поэтому эффективнее использовать изображение градиента.

:!: Пример: Градиент с тремя точками останова, трансформирован в диагональ
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: 640; height: 480; visible: true;
    Rectangle
    {
        anchors.fill: parent
        gradient: Gradient
        {
            GradientStop{position: 0.0; color: "blue"}
            GradientStop{position: 0.7; color: "gold"}
            GradientStop{position: 1.0; color: "silver"}
        }
        rotation: 30
        scale: 1.5
    }
}

Рисование Canvas


Canvas представляет собой элемент холста, на котором можно выполнять растровые операции, по сути аналогичен QPaintDevice.
Сам QML описательный язык, поэтому алгоритмы рисования реализуются с использованием JavaScript, в свойстве обработки onPaint.

:!: Пример: Прикольный узор, нарисованный на холсте
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: 480; height: 480; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Canvas
        {
            anchors.fill: parent;
            onPaint:
            {
                function drawFantasy()
                {
                    ctx.beginPath();
                    ctx.translate(parent.width / 2, parent.height / 2);
                    var fAngle = 91 * 3.14156 / 180
                    for(var i = 0; i < 300; ++i)
                    {
                        var n = i * 2;
                        ctx.moveTo(0, 0);
                        ctx.lineTo(n, 0);
                        ctx.translate(n, 0);
                        ctx.rotate(fAngle)
                    }
                    ctx.closePath();
                }
 
                var ctx = getContext("2d");
                ctx.clearRect(0, 0, parent.width, parent.height);
                ctx.save();
                ctx.strokeStyle = "black";
                ctx.lineWidth = 1;
                drawFantasy();
                ctx.stroke();
                ctx.restore();
            }
        }
    }
}
:!: Пример: Градиент на холсте
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: 480; height: 480; visible: true;
    Rectangle
    {
        anchors.fill: parent
 
        Canvas
        {
            id: canv
            width: 320; height: 320;
            onPaint:
            {
                var ctx = getContext("2d");
                ctx.strokeStyle= "blue";
                ctx.lineWidth = 15;
                var gradient = ctx.createLinearGradient(canv.width, canv.height, 0, 0);
                gradient.addColorStop(0, "Indigo");
                gradient.addColorStop(0.5, "Bisque");
                gradient.addColorStop(1, "ForestGreen");
                ctx.fillStyle = gradient;
                ctx.fillRect(0, 0, canv.width, canv.height);
                ctx.strokeRect(0, 0, canv.width, canv.height);
            }
        }
    }
}       

Пользовательский ввод

Область мыши


Для получения событий мыши служат специальные элементы - MouseArea, по сути просто прямоугольные области, в которых осуществляется ввод информации от мыши.

:!: Пример: Нажатие левой и правой кнопок мыши
import QtQuick 2.12; import QtQuick.Controls 2.2; import QtQuick.Layouts 1.12
 
ApplicationWindow
{
    width: 300; height: 300; visible: true;
    Rectangle
    {
        anchors.fill: parent
        color: "lightgreen"
        Text
        {
            id: txt
            anchors.centerIn: parent
            text: "<h1>This is text<br>Click here</h1>"
            horizontalAlignment: Text.AlignHCenter
        }
        MouseArea
        {
            anchors.fill: parent
            acceptedButtons: Qt.LeftButton | Qt.RightButton
            onPressed:
            {
                if(mouse.button == Qt.LeftButton)
                    parent.color= "red"
                else
                    parent.color= "blue"
            }
            onReleased: parent.color= "lightgreen"
        }
    }
}

Так же, можно использовать свойство containsMouse, для обнаружения находится ли курсор над областью.
Аналогично можно использовать свойства onEntered и onExit.

:!: Пример: Обнаружение находится ли курсор над областью
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 300; height: 300; visible: true;
    Rectangle
    {
        anchors.fill: parent
        color: mousearea.containsMouse ? "red" : "lightgreen"
        Text
        {
            anchors.centerIn: parent
            text: "<h1>Hover me</h1>"
        }
        MouseArea
        {
            id: mousearea
            anchors.fill: parent
            hoverEnabled: true
        }
    }
}

Сигналы


Сигналы в QML это события, которые уже прикреплены к свойствам, с кодом исполнения в них, эти свойства называются с префиксом on и являются по сути слотами.

Можно определять собственные сигналы:
signal <name>[(<type> <value>, …)]
К каждому такому сигналу автоматически создастся соответствующий обработчик (слот), с префиксом on.

Насколько я понимаю, вызвать наш сигнал может только какое то действие т.е. стандартный сигнал (точнее его обработчик on..), поэтому любой собственный сигнал будет так или иначе связан с уже существующим, стандартным сигналом.., плюс есть как минимум в том, что наши собственные сигналы будут доступны на уровнях выше т.е. извне, в случае например объявления объекта в отдельном файле.

:!: Пример: Сигнал движения курсора мыши
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 300; height: 300; visible: true;
    Rectangle
    {
        anchors.fill: parent
        color: mousearea.containsMouse ? "red" : "lightgreen"
        signal myMouseSignal(int x, int y)
        onMyMouseSignal:
        {
            txt.text= "<h1>X:"+x +"; Y:"+y +"</h1>"
        }
        Text
        {
            id: txt
            anchors.centerIn: parent
        }
        MouseArea
        {
            anchors.fill: parent
            hoverEnabled: true
            onMouseXChanged: parent.myMouseSignal(mouseX, mouseY)
            onMouseYChanged: parent.myMouseSignal(mouseX, mouseY)
        }
    }
}
:!: Пример: Собственный элемент+ передача сигнала наружу
// Файл button.qml
import QtQuick 2.0
 
BorderImage
{
    property alias text: txt.text
    signal clicked;
    source: "qrc:/button.png"
    width: txt.width +15
    height: txt.height +15
    border {left: 15; top: 12; right: 15; bottom: 15}
    Text
    {
        id: txt
        color: "white"
        anchors.centerIn: parent
    }
    MouseArea
    {
        anchors.fill: parent
        onClicked: parent.clicked();
        onPressed: parent.source= "button-press.png"
        onReleased: parent.source= "button.png"
    }
}
 
// Основной файл
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 150; height: 100; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Button
        {
            anchors.centerIn: parent
            text: "Click this"
            onClicked: text= "Clicked"
        }
    }
}

Ввод с клавиатуры


В основном ввод с клавиатуры обрабатывается двумя элементами: TextInput (однострочный) и TextEdit (многострочный).
Размер элемента будет соответствовать введенному тексту, что бы при пустом вводе элемент не исчезал, нужно задавать мин.ширину

:!: Пример: Простое поле ввода текста
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: txt.width + 20; height: 100; visible: true;
    Rectangle
    {
        anchors.fill: parent
        TextInput
        {
            id: txt
            anchors.centerIn: parent
            color: "red"
            text: "Text in this"
            font.pixelSize: 32
            focus: true
        }
    }
}

Фокус


Если на форме один элемент, он получает фокус автоматом, далее, фокус можно изменить ручным выбором мышкой либо табом. Програмно можно воспользоваться свойством focus.
Нетекстовые элементы так же могут иметь фокус.
Для управления порядком фокуса табом, используется т.н. прикрепляемое свойство «KeyNavigation.tab: <FocusThisElement>». В этом свойстве так же доступны клавиши типа KeyNavigation.left, KeyNavigation.right, KeyNavigation.up, KeyNavigation.down и т.д.

:!: Пример: Два поля ввода, выделение их фокусировки
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 200; height: 80; visible: true;
    Rectangle
    {
        anchors.fill: parent
        TextEdit
        {
            anchors
            {
                left: parent.left
                right: parent.horizontalCenter
                top: parent.top
                bottom: parent.bottom
            }
            text: "Text1\nText1\nText1"
            font.pixelSize: 20
            color: focus ? "red":"black"
            focus: true
        }
        TextEdit
        {
            anchors
            {
                left: parent.horizontalCenter
                right: parent.right
                top: parent.top
                bottom: parent.bottom
            }
            text: "Text2\nText2\nText2"
            font.pixelSize: 20
            color: focus ? "red":"black"
        }
    }
}

Сырой ввод


С помощью прикрепляемого свойства Keys можно получить доступ к событиям клавиатуры, с полной информацией о событии.

:!: Пример: Перемещение элемента с помощью клавиш-стрелок
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 200; height: 80; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Text
        {
            x: 20; y: 20;
            text: "Move this text"
            horizontalAlignment: Text.AlignHCenter
            Keys.onLeftPressed: x -= 3
            Keys.onRightPressed: x += 3
            Keys.onUpPressed: y -= 3
            Keys.onDownPressed: y += 3
            focus: true
        }
    }
}

При помощи Keys.forwardTo можно пересылать события другим элементам, для дальнейшей обработки.

:!: Пример: Так же, можно сделать это в одном обработчике
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 200; height: 80; visible: true;
    Rectangle
    {
        anchors.fill: parent
        Text
        {
            x: 20; y: 20;
            text: "Move this text"
            horizontalAlignment: Text.AlignHCenter
            focus: true
            Keys.onPressed:
            {
                if(event.key === Qt.Key_Left) { x -= 3; }
                else if(event.key === Qt.Key_Right) { x += 3; }
                else if(event.key === Qt.Key_Down) { y += 3; }
                else if(event.key === Qt.Key_Up) {y -= 3; }
                else if(event.key === Qt.Key_Plus) {font.pixelSize++; }
                else if(event.key === Qt.Key_Minus) {font.pixelSize--; }
            }
        }
    }
}

Мультитач


Область региона- MultiPointTouchArea. Он содержит в себе элементы обработки события касания- TouchPoint, их должно быть столько, сколько одновременных касаний мы собираемся принимать, его можно сравнить с MouseArea.

:!: Пример: Обработка пяти одновременных касаний
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 400; height: 400; visible: true
    Rectangle
    {
        anchors.fill: parent
        color: "black"
        MultiPointTouchArea
        {
            anchors.fill: parent
            minimumTouchPoints: 1
            maximumTouchPoints: 5
            touchPoints:
            [
                TouchPoint {},
                TouchPoint {},
                TouchPoint {},
                TouchPoint {},
                TouchPoint {}
            ]
            Repeater
            {
                model: parent.touchPoints
                Rectangle
                {
                    color: "white"
                    x: modelData.x; y: modelData.y
                    width: 30; height: 30
                    visible: modelData.pressed
                }
            }
        }
    }
}

Так же, у TouchPoint есть следующие св-ва:

pressed При касании == true
pressure Сила нажатия (не все устр-ва поддерживают)
previous{X,Y} Пред координаты касания
start{X,Y} Начальные координаты касания
x,y Текущие координаты касания

Анимация

Анимация при изменении свойств


Для анимации свойств существует элемент PropertyAnimation, с ним можно менять сразу несколько свойств одновременно.

:!: Пример: Одновременное изменение x и y
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 400; height: 400; visible: true
    Rectangle
    {
        anchors.fill: parent
        color: "lightgreen"
        Image
        {
            id: img
            x: 0; y: 0;
            source: "qrc:/button.png"
        }
        PropertyAnimation
        {
            target: img
            properties: "x,y"
            // Начальное и конечное значение для св-в
            from: 0; to: 400 - img.height
            // Длительность мс
            duration: 1500
            running: true
            loops: Animation.Infinite
            // Режим. скорость и т.д. есть интерактивный редактор
            easing.type: Easing.OutExpo
        }
    }
}

Изменение числовых значений


Более эффективная реализация для real и int.

:!: Пример: Изменение размера вложенного прямоугольника x2
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 300; height: 100; visible: true
    Rectangle
    {
        id: par
        anchors.fill: parent
        color: "lightgreen"
        Rectangle
        {
            x: 0; y: 0;
            height: 100
            color: "red"
            NumberAnimation on width
            {
                id: anim1
                from: 300; to: 0
                duration: 2000
                easing.type: Easing.InOutCubic
                onStopped:
                {
                    anim2.start()
                }
            }
 
            NumberAnimation on width
            {
                id: anim2
                from: 0; to: 300
                duration: 2000
                easing.type: Easing.InOutCubic
                running: false
                onStopped:
                {
                    anim1.start()
                }
            }
 
        }
    }
}

Изменение цвета


ColorAnimation управляет изменением цвета, так же используется from и to.

:!: Пример: Изменение цвета
import QtQuick 2.12; import QtQuick.Controls 2.2
 
ApplicationWindow
{
    width: 300; height: 100; visible: true
    Rectangle
    {
        anchors.fill: parent
        ColorAnimation on color
        {
            from: "lightgreen"
            to: "red"
            duration: 1500
            running: true
            loops: Animation.Infinite
        }
    }
}

Поворот


:!: Пример:
 

Анимация поведения


:!: Пример:
 

:!: Пример:
 
develop/qt/quick2.1630229130.txt.gz · Последнее изменение: 2021/08/29 09:25 — admin