====== Qt Quick: Общее, Элементы, Размещение ======
**Qt Quick** - набор технологий для создания пользовательского интерфейса.\\
Подход основан на использовании описательного языка **QML** (Qt Meta-object Language). Принцип схож с форматом **JSON**.\\
В **QML** встроен интерпретатор **JavaScript**, поэтому легко принимает вставки данного языка.\\
**QML** содержит множество модулей, как общих для QT так и своих, подключаемых директивой **import**.\\
Объекты в **QML** располагаются древовидной структурой.\\
Объекты содержат свойства в формате **ключ: значение**, доступ к объекту можно получить через идентификатор **id**, к родителю можно обращаться через **parent**.\\
В среде **Qt Creator** вроде как можно работать с **QML** интерактивно.\\
===== JavaScript =====
**Java** интерпретируется и применяется сходу, например тут- **"width: parent.width / 5"**, значение сначала высчитывается, на **java**, после этого присваивается свойству.\\
Можно вставлять целые функции:
Rectangle
{
function maximum(a, b)
{
return a > b ? a:b;
}
width: maximum(parent.width, 100)
}
Функции можно импортировать из внешних файлов
import "myfile.js" as MyScripts
(...)
Rectangle
{
width: MyScripts.maximum(parent.width, 100)
}
Есть ряд полезных функций для отладки:
| console.count() | Кол-во вызова кода |
| console.[debug(); log(); info(); error(); warn()]; print() | Вывод сообщений |
| console.[time(); timeEnd()] | Замер времени |
| console.trace() | Цепочка вызовов java не более 10 |
:!: Пример: Простое окно с полем ввода
import QtQuick 2.12
import QtQuick.Window 2.12
Window
{
width: 640
height: 480
visible: true
title: "Hello World"
MouseArea
{
anchors.fill: parent
onClicked: console.log('Clicked on background. Text: "'+ textEdit.text +'"')
}
TextEdit
{
id: textEdit
text: "Enter your text123.."
verticalAlignment: Text.AlignVCenter
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalLeft
anchors.topMargin: 15
Rectangle
{
anchors.fill: parent
anchors.margins: -10
color: "transparent"
border.width: 1
}
}
}
===== Объекты =====
==== Не визуальные ====
----
| Column; Row; Grid, Flow, Positioner; etc | Для размещения элементов |
| Timer; Loader; Connections, WorkerScript; Binding; etc | Инструменты |
| [Property; Number; Color; Parallel]Animation; etc | Анимация |
| [List; Xml; VisualData; VusialItem]Model; ListElement; etc | Модели |
| [Mouse; Drop; Pinch; MultiPointTouch]Area; [Mouse; Key]Event; etc | Пользовательский ввод |
==== Визуальные ====
----
| Item | Базовый тип для всех элементов, может выступать в роли окна приложения |
| Rectangle | Заполненная прямоугольная область, мб с контуром |
| Image (BorderImage) | Растровое изображения (с контуром) |
| Text | Форматированный текст |
| TextEdit (TextInput) | Ввод и отображение текста |
| Window | Элемент главного окна приложения |
| WebView | Отображение веб содержания |
Отдельная подгруппа представлений для размещения элементов: **ListView**, **GridView**, **PathView**;
**Элементы-потомки** отображаются **относительно и внутри** своего **родительского** элемента.
:!: Пример: 3 уровня элементов
import QtQuick 2.8
import QtQuick.Window 2.2
Window
{
visible: true
width: 360
height: 360
Rectangle
{
color: "darkkhaki"
x: 100
y: 50
width: 170
height: 200
border.color: "black"
border.width: 10
radius: 40
smooth: true
Text
{
x: 50
y: 50
text: "Hi, this is string of my text"
}
}
}
==== Свойства элементов ====
----
Стандартные свойства для всех элементов:
| x; y; z; position | Позиционирование |
| width; height; implicit[Width; Height] | Задание/получение размеров |
| rotation; scale; clip; transform; smooth; transformOrigin; etc | Графические операции и преобразования |
| anchors | Фиксация |
| id; parent | Ссылки на элементы |
| enabled; focus | Доступность; Фокус |
| visible; opacity; visibleChildren | Видимость |
| states; state; transitions | Состояние и переход |
| layer | Работа со слоями |
| children; childrenRect | Дочерние элементы |
| onWidthChanged; onHeightChanged; etc | Методы, вызываемые при изменении свойств, в них можно размещать код |
:!: Пример: Взаимосвязанные свойства объектов
import QtQuick 2.8
import QtQuick.Window 2.2
Window
{
visible: true
width: 360
height: 360
Rectangle
{
id: redrect
color: "red"
x: 0
y: 0
width: parent.width / 2
height: parent.height / 2
}
Rectangle
{
color: "green"
x: redrect.width
y: redrect.height
width: redrect.width
height: redrect.height
}
}
=== Собственные свойства ===
----
**property <тип> <имя>[:значение]**\\
Элементам можно задавать собственные свойства. Они могут содержать значения, а так же для них создаются методы **onX** для реагирования на изменения этих свойств.\\
Необходимо указывать **типы данных**, они строго типизированы (bool, double, enumeration, int, list, real, string, time, url, var, color, date, font, matrix4x4, point, rect, size, Vercor[2,3,4]d).\\
==== Собственные элементы ====
----
Определяются в отдельных файлах, **один файл - один элемент**. Используются так же как и стандартные.\\
Элементы расположенные в одном каталоге **автоматически доступны** друг для друга.\\
Из вне будут доступны только свойства базового элемента, но не св-ва вложенных, для этого можно переопределить определить их **алиасом** в базовом элементе.\\
:!: Пример: Собственный элемент
// Описание элемента в отдельном файле, в папке в проектом
import QtQuick 2.8
Rectangle
{
property alias text: txt.text
property string name: "TextFielddd"
width: txt.width
height: txt.height
Text
{
id: txt
x: 0
y: 0
}
}
// Использование элемента
import QtQuick 2.8
import QtQuick.Window 2.2
Window
{
visible: true; width: 360; height: 360
TextField
{
x: 10
y: 20
color: "yellow"
text: "This Text in myTextField
Second String"
border.width: 1
}
}
==== Собственные модули ====
----
Коллекции QML элементов можно объединять в модули и использовать повторно, подключив директивой **import**.\\
Располагают их в отдельной папке, создают файл **qmldir** с картой описания qml файлов элементов, с указанием версии.\\
==== Динамическое создание элементов ====
----
Элемент **Repeater** позволяет производить элементы используя любой тип модели данных (число, массив, набор JSON), это инструкция к созданию, а элемент внутри, является шаблоном.\\
:!: Пример: 4 элемента в столбик, из массива значений
import QtQuick 2.8
import QtQuick.Window 2.2
Window
{
visible: true; width: 360; height: 360
Repeater
{
model: ["one", "two", "three", "four"]
Text
{
text: modelData // обращение к массиву значений
y: index * 20 // index - номер текущего элемента
}
}
}
**Flickable** - типа скроллбара, в нем можно располагать элементы большого размера
==== Готовые элементы ====
----
В модуле **QtQuick.Controls** содержится ряд готовых элементов GUI.\\
Такие элементы как: CheckBox, DelayButton, RadioButton, PoundButton, Switch, ToolButton, Button, BusyIndicator, ComboBox, Dial, Label, PageIndicator, ProgressBar, RangeSlider, Slider, SpinButton, ToolBar, Tumbler.\\
Область основного окна делится на три зоны: Верхняя (header), Нижняя (footer) и Рабочая (в середине)
:!: Пример: Элементы в трех зонах
import QtQuick 2.8
import QtQuick.Window 2.2
Window
{
visible: true; width: 360; height: 360
header: ToolBar
{
//AnyElements
}
footer: ToolBar
{
//AnyElements
}
//AnyElements in Center
}
Так же, в модуле **QtQuick.Extras** есть аналогичные, но выглядящие более специфично, элементы.\\
==== Диалоговые окна ====
----
В основном это: **FileDialog**, **FontDialog**, **ColorDialog** и **MessageDialog**.\\
:!: Пример: Три диалога, после выбора месседж с выбранным вариантом
import QtQuick 2.8
//import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow // Window
{
visible: true; width: 200; height: 150
Repeater
{
id: repeater
model: [colorDialog, fontDialog, fileDialog]
Button
{
y: index * (parent.height / repeater.count)
height: parent.height / repeater.count
width: parent.width
text: modelData.title
onClicked:
{
messageDialog.visible = false
modelData.visible = true
}
}
}
ColorDialog
{
id: colorDialog
visible: false
modality: Qt.WindowModal
title: "Select color"
color: "blue"
onAccepted:
{
messageDialog.informativeText = "Selected color: "+ color
messageDialog.visible = true
}
}
FontDialog
{
id: fontDialog
visible: false
modality: Qt.WindowModal
title: "Select font"
onAccepted:
{
messageDialog.informativeText = "Selected font: "+ font
messageDialog.visible = true
}
}
FileDialog
{
id: fileDialog
visible: false
modality: Qt.WindowModal
title: "Select file"
folder: "C:\\Users\\"
nameFilters: ["All files (*)"]
onAccepted:
{
messageDialog.informativeText = "Selected file: "+ fileUrls
messageDialog.visible = true
}
}
MessageDialog
{
id: messageDialog
visible: false
modality: Qt.NonModal
title: "Message"
}
}
===== Управление размещением =====
==== Фиксаторы ====
----
**Фиксатор (anchors)** позволяет определить расположение одного элемента относительно других.\\
В **QML** все элементы вложены друг в друга и располагаются элементы относительно своего родителя.\\
Для фиксации можно использовать свойства: left, right, top, bottom, {horizontal,vertical}Center
:!: Пример: Размещение элемента в центре родителя
import QtQuick 2.12; import QtQuick.Window 2.12
Window
{
width: 640; height: 480; visible: true;
Rectangle
{
anchors.fill: parent
Text
{
text: "This is text in text-element"
anchors.centerIn: parent
// или аналогично:
//anchors.horizontalCenter: parent.horizontalCenter
//anchors.verticalCenter: parent.verticalCenter
}
}
}
Эти же свойства можно использовать для заполнения элементом области
:!: Пример: Заполнение области
import QtQuick 2.12; import QtQuick.Window 2.12
Window
{
width: 640; height: 480; visible: true;
Rectangle
{
// Для группы свойств
anchors
{
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
}
// Аналогично
//anchors.fill: parent
}
}
:!: Пример: Размещение двух элементов с перекрытием (наложением)
import QtQuick 2.12; import QtQuick.Controls 2.2
ApplicationWindow
{
width: 640; height: 480; visible: true;
Rectangle
{
anchors.fill: parent
Rectangle
{
id: firstRec
color: "red"
width: parent.width / 1.5
height: parent.height / 1.5
anchors.left: parent.left
anchors.top: parent.top
}
Rectangle
{
opacity: 0.5
color: "blue"
anchors
{
top: firstRec.verticalCenter
left: firstRec.horizontalCenter
right: parent.right
bottom: parent.bottom
}
}
}
}
:!: Пример: Два элемента по краям, третий заполняет центр + отступы
import QtQuick 2.12; import QtQuick.Controls 2.2
ApplicationWindow
{
width: 640; height: 480; visible: true;
Rectangle
{
anchors.fill: parent
Rectangle
{
id: leftrec
width: 60
color: "blue"
anchors
{
left: parent.left
top: parent.top
bottom: parent.bottom
topMargin: 10
bottomMargin: 10
}
}
Rectangle
{
id: rightrec
width: 60
color: "blue"
anchors
{
right: parent.right
top: parent.top
bottom: parent.bottom
topMargin: 10
bottomMargin: 10
}
}
Rectangle
{
id: centerrec
color: "green"
anchors
{
top: parent.top
bottom: parent.bottom
left: leftrec.right
right: rightrec.left
}
}
}
}
==== Традиционные размещения ====
----
Размещения являются элементами
| Row, RowLayout | Горизонтальное размещение, аналог QHBoxLayout |
| Column, ColumnLayout | Вертикальное размещение, аналог QVBoxLayout |
| Grid, GridLayout | Табличное размещение, аналог QGridLayout |
| StackLayout | Одновременно можно видеть только один элемент, аналог QStackLayout |
Содержат свойства **spacing** и **layoutDirection**, для установки промежутков и управления направлением размещения.\\
Элементы со словом **layout**, содержатся в модуле **QtQuick.Layouts** и обладают доп. свойством **Layout**:
| .minimum{Width,Heigth} | минимальная ширина/высота |
| .maximum{Width,Heigth} | максимальная ширина/высота |
| .preferred{Width,Heigth} | предпочтительная ширина/высота |
| .fill{Width,Heigth} | заполнение по ширине/высоте элемента |
:!: Пример: Горизонтальное размещение
import QtQuick 2.12; //import QtQuick.Window 2.12
import QtQuick.Controls 2.2
ApplicationWindow
{
width: 640; height: 480; visible: true;
Rectangle
{
anchors.fill: parent
Row
{
anchors.centerIn: parent
spacing: 10
Rectangle
{
width: 64; height: 64; color: "red"
}
Rectangle
{
width: 64; height: 64; color: "yellow"
}
Rectangle
{
width: 64; height: 64; color: "green"
}
}
}
}
:!: Пример: Горизонтальное размещение RowLayout+ замещение элементами
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
RowLayout
{
anchors.fill: parent
spacing: 10
Layout.margins: 10
Rectangle
{
Layout.minimumWidth: 64; Layout.minimumHeight: 64; color: "red"; Layout.fillHeight: true
}
Rectangle
{
Layout.minimumWidth: 64; Layout.minimumHeight: 64; color: "yellow"; Layout.fillWidth: true
}
Rectangle
{
Layout.minimumWidth: 64; Layout.minimumHeight: 64; color: "green"; Layout.fillHeight: true
}
}
}
}
==== Размещение в виде потока ====
----
Упорядочивает элементы змейкой, пытаясь уместить их как можно больше.\\
:!: Пример: Десять элементов, размещаются потоком
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
Flow
{
anchors.fill: parent
anchors.margins: 20
spacing: 20
Repeater
{
model:
{
var v = new Array(10);
for(var i= 0; i < v.length; ++i)
v[i]= i % 2 ? "green" : "red"
return v;
}
Rectangle
{
width: 64; height: 64; radius: 32; color: modelData
Text
{
color: "white"; font.pixelSize: 48; font.family: "Courier"; anchors.centerIn: parent; text: index
}
}
}
}
}
}