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