# Сигналы, слоты, свойства

Copyright&nbsp;©&nbsp;2016–2023 ООО&nbsp;«Открытая мобильная платформа».
Этот документ предоставляется в&nbsp;соответствии
с&nbsp;[Публичной лицензией Creative Commons с&nbsp;указанием авторства версии&nbsp;4.0 Международная](../../LICENSE.CC-BY-4.0.ru.md).

## Описание свойств и методов

Определение новых свойств в QML компонентах осуществляется с помощью приведенной на слайде конструкции.
В качестве propertyType могут выступать такие типы как int, bool, string, var (универсальный
тип переменной), массивы и словари, а также типы предоставляемые модулем QtQuick такие, как date, color.
Полный список можно посмотреть в документации.
Конструкция позволяет проинициализировать свойство при объявлении.

Кроме определения свойств, которые хранят непосредственно какое-либо значение, средства QML
позволяют создавать alias (псевдо свойства), которые могут быть связаны с другими существующими свойствами.
Операция чтения или записи такого свойства осуществляется как чтение или запись связанного с ним свойства.
Синтаксис добавления alias похоже на объявление обычного свойства.
Так как псевдо свойство имеет тип аналогичный связанному свойству, явное указание типа заменено
на ключевое слово alias.
Вместо значения по умолчанию для alias необходимо обозначить свойство, на которое оно ссылается.
При этом нужно указать идентификатор объекта внутри компонента, а затем через точку его свойство.

Как было сказано ранее QML является декларативным языком.
Однако, QML позволяет использовать конструкции с императивным кодом на языке Javascript.
Такие конструкции могут быть использованы при связывании свойств, внутри обработчиков сигналов
или в качестве JS функций в компонентах.

Определение нового метода: function methodName(arguments) { JavaScript }.

Определение нового сигнала:  signal signalName(arguments).

QML предоставляет возможности для использования системы сигналов Qt.
Компоненты могут генерировать сигналы (своего рода уведомления о каком-либо событии (например,
сигнал о клике на элемент)) и обрабатывать их в соответствующих методах (слотах).
Для каждого компонента определен стандартный набор сигналов, который может быть расширен.
Для всех сигналов автоматически создаются методы для их обработки, имеющие название on<SignalName>.

Вывод в консоль: console.log(data).

Подключение внешней библиотеки JS: import "path_to_file.js" as Alias.

## Определение свойств

Свойства, определенные для корневого объекта, доступны  для чтения и изменения другими компонентами извне.
Помимо стандартных свойств, определенных для корневого элемента, QML позволяет добавлять
собственные свойства.
Для них также доступен механизм связывания.
Для добавления нового свойства необходимо указать его название и тип.
Название должно быть уникальным внутри компонента.
Для свойства может быть определено значение по умолчанию (опционально).
Пример демонстрирует добавление свойства currentImage типа строки со значением
по умолчанию "default-image.png".

## Привязывание свойств

К значению свойства можно обращаться по его имени propertyName из кода,
определённого в propertyOwner - владельце свойства.

В другом объекте к значению свойства можно обращаться по id владельца свойства и имени свойства,
написанных через точку.

## Binding — привязки к свойствам других объектов

Привязки свойств приводят к зависимости между свойствами различных объектов.

*	target : Объект для обновления.
*	value : Значение, которое будет установлено для целевого объекта и свойства.
	Это может быть константа (что не очень полезно) или связанное выражение.
*	property :  Свойство для обновления.
	Это может быть и групповое свойство.
*	when : Это свойство сохраняется, когда привязка активна.
	Ему должно присваиваться выражение, которое оценивается как true, если вы хотите,
	чтобы привязка была активной.

## Определение методов

К собственным QML компонентам можно добавлять методы.
Для этого используется обыкновенный синтаксис javascript.
Метод объявляется созданием javascript функции.
В дальнейшем метод будет доступен при обращении по id компонента.
В данном примере метод changeColor() используется для изменения цвета прямоугольника на переданный.

## Создание и обработка сигналов

Собственным QML-компонентам можно добавлять сигналы.
Сигналы служат для того, чтобы сообщить какому-либо объекту о каком либо событии.
Для объявления сигнала необходимо использовать ключевое слово signal, затем указывать название
сигнала и список параметров с типами в скобках.
Для того, чтобы инициировать сигнал, необходимо вызвать его как обыкновенный метод.
Для обработки сигналов существуют соответствующие свойства, которым присваиваются обработчики.
Данные свойства начинаются с приставки on, далее идёт название самого сигнала с большой буквы.
Внутри тела обработчика доступны передаваемые свойства по названиям, указывающимся при объявлении сигнала.

Данный пример изменяет цвет кнопки после нажатия на неё.
Сигнал customButtonClicked() используется для того, чтобы уведомить о нажатии.
В качестве параметра передаётся новый цвет кнопки.
Данный параметр используется в обработчике для вывода нового цвета в консоль.

## Подключение и отключение обработчиков сигналов

Также обработчики сигналов можно подключать с помощью метода connect().
Данный метод вызывается на объекте сигнала объекта.
Следует обратить внимание, что обращение к сигналу производится без использования приставки on.
Метод-обработчик может принимать параметры от сигнала (в данном примере объект mouse).

Отключаются сигналы аналогичным образом, но с использованием метода disconnect(), которому
передаётся функция-обработчик, подключенная ранее.
 
## Сигналы изменения свойств

У каждого свойства, объявленного в QML есть обработчик изменения значения.
Он начинается с приставки on, как обыкновенный сигнал, далее идёт название свойства с большой буквы
и заканчивается словом Changed.

В текущем примере мы можем использовать сигнал изменения цвета для того, чтобы выводить его код на консоль.
 
## Connections — обработчик сигналов других объектов

Объектам можно устанавливать обработчики событий с помощью объекта Connections.
Он позволяет задать обработчик внутри своего тела, а целевой объект с помощью свойства target.
Данный способ установки обработчиков полезен, если объект объявлен глобально и и необходимо указать
какой-то обработчик на какой-либо странице.
В этом случае невозможно установить обработчик в месте определения, поэтому используется
объект Connections.
По умолчанию объект будет выбрасывать runtime исключение, если производится подключение
к несуществующему сигналу.
Чтобы игнорировать такие сигналы, необходимо установить свойству ignoreUnknownSignals значение true.

## MouseArea — обработчик нажатий

MouseArea — это невидимый элемент, который обычно используется вместе с видимым элементом,
чтобы обеспечить обработку этого элемента мышью.
Свойства MouseArea:

*	mouseX, mouseY : real — координаты курсора;
*	pressed : bool — было ли нажатие;
*	clicked(MouseEvent mouse) — сигнал для щелчка;
*	pressed(MouseEvent mouse) — сигнал для нажатия;
*	pressAndHold(MouseEvent mouse) — сигнал для нажатия дольше чем 800ms;
*	released(MouseEvent mouse) — сигнал, что кнопка отпущена.

Сигналы передают объект типа MouseEvent.
Он содержит следующие свойства:

*	x, y : int — координаты курсора;
*	wasHeld : bool — долгое ли нажатие.

## Пример кнопки

Пример создания кнопки с помощью MouseArea.
Площадь MouseArea соответствует площади родительского элемента Rectangle.

Нажатие на кнопку обрабатывается в слоте onClicked.

## PinchArea — обработчик двухпальцевых жестов

PinchArea — это невидимый элемент, который обычно используется в сочетании с видимым элементом
для обеспечения обработки жестов стягивания для этого элемента.
Свойство enabled используется для включения и отключения обработки стягивания для заданного элемента.
При отключенном свойстве область зажима становится прозрачной для событий мыши/касания. По умолчанию true.
PinchArea можно использовать двумя способами:

*	установка pinch.target чтобы обеспечить автоматическое взаимодействие с элементом;
*	использование обработчиков onPinchStarted, onPinchUpdated и onPinchFinished.

## PinchArea: свойства

pinch обеспечивает удобный способ заставить элемент реагировать на жесты стягивания.

*	pinch.target указывает идентификатор элемента для перетаскивания.
*	pinch.active указывает, перетаскивается ли в данный момент целевой элемент.
*	pinch.minimumScale и pinch.maximumScale ограничивают диапазон свойства Item.scale,
	но не свойства PinchEvent scale.
*	pinch.minimumRotation и pinch.maximumRotation ограничивают диапазон свойства Item.rotation,
	но не свойства PinchEvent rotation.
*	pinch.dragAxis указывает, что перетаскивание не разрешено (Pinch.NoDrag), может быть сделано
	горизонтально (Pinch.XAxis), вертикально (Pinch.YAxis), или в обоих направлениях (Pinch.XAndYAxis).
*	pinch.minimum и pinch.maximum ограничивают, как далеко целевой элемент может быть перетащен
	вдоль соответствующих осей.

## PinchArea: сигналы

pinchFinished() испускается, когда область стягивания обнаруживает, что жест стягивания завершен.
Параметр pinch (не совпадает со свойством pinch) предоставляет информацию о жесте стягивания,
включая масштаб, центр и угол стягивания.

pinchStarted() испускается, когда область стягивания обнаруживает, что начался жест стягивания:
обнаружены две точки касания (пальцы), и они переместились за порог startDragDistance для начала жеста.
Параметр pinch (не совпадает со свойством pinch) предоставляет информацию о жесте стягивания,
включая масштаб, центр и угол стягивания.
Во время сигнала pinchStarted эти значения сбрасываются до значений по умолчанию, независимо
от результатов предыдущих жестов: pinch.scale будет 1.0 и pinch.rotation будет 0.0.
Когда жест продолжается, pinchUpdated сообщает об отклонении от этих параметров по умолчанию.
Чтобы проигнорировать этот жест, установите pinch.accepted как false.
Жест будет отменен, и никакие дальнейшие события не будут отправлены.

pinchUpdated() испускается, когда область стягивания обнаруживает, что жест стягивания изменился.
Параметр pinch предоставляет информацию о жесте стягивания, включая масштаб, центр и угол стягивания.
Эти значения отражают изменения только с начала текущего жеста и поэтому не ограничены минимальными
и максимальными пределами в свойстве pinch.

smartZoom() испускается, когда область стягивания обнаруживает умный жест масштабирования.
Параметр pinch предоставляет информацию о жесте стягивания, включая местоположение, в котором
произошел жест. pinch.scale будет больше нуля, когда жест указывает, что пользователь хочет ввести
smart zoom, и ноль при выходе (хотя обычно один и тот же жест используется для переключения
между двумя состояниями).

## DropArea и Drag

DropArea — это невидимый элемент, который получает события при перетаскивании по нему
других элементов.
Свойство keys можно использовать для фильтрации событий перетаскивания, которые не включают
соответствующий ключ.
Свойство drag.source передается источнику события перетаскивания как получателю объекта,
который перетаскивается.

Свойство Drag attached можно использовать для уведомления DropArea при перетаскивании элемента.
Используя свойство Drag attached, любой элемент можно сделать источником событий перетаскивания в сцене.
При активном перетаскивании элемента любое изменение его положения вызовет событие перетаскивания,
которое будет отправлено в любую DropArea, пересекающуюся с новой позицией элемента.
Другие элементы, реализующие обработчики событий перетаскивания, также могут получать эти события.

## DropArea и Drag: пример

В примере прямоугольник отображается, если по его родительской DropArea протаскивается объект.

## DropArea и Drag: пример [2]

В следующем фрагменте показано, как элемент можно перетащить с помощью MouseArea.
Однако перетаскивание не ограничивается перетаскиванием мыши; все, что может перемещать элемент,
может генерировать события перетаскивания, включая события касания, анимации и привязки.

## DropArea и Drag

Перетаскивание можно прервать либо отменив его с помощью Drag.cancel(), либо установив
Drag.active как false, либо инициировав новое событие перетаскавания вызовом Drag.drop().
Если событие перетаскивания принято, Drag.drop() вернет действие перетаскивания, выбранное
получателем события, в противном случае он вернет Qt.IgnoreAction.

## DropArea и Drag: пример [3]

В примере настраивается элемент Drag.
dragArea будет определена на следующем слайде.


## DropArea и Drag: пример [4]

Drag.imageSource  содержит URL-адрес изображения, которое будет использоваться для представления
данных во время операции перетаскивания.
Изменение этого свойства после начала операции перетаскивания не будет иметь никакого эффекта.

Пример на слайде является продолжением предыдущего примера.
В нем содержимое элемента используется как изображение перетаскивания.

## MultiPointTouchArea — обработчик нескольких точек касания

MultiPointTouchArea-это невидимый элемент, который используется для отслеживания нескольких точек касания.
Свойство Item::enabled используется для включения и отключения сенсорной обработки.
При отключении сенсорная область становится прозрачной для мыши и сенсорных событий.

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

mouseEnabled определяет, будет ли MultiPointTouchArea обрабатывать события мыши тоже.
Если оно true (по умолчанию), сенсорная область будет обрабатывать мышь так же, как и одну точку
касания; если это false, сенсорная область будет игнорировать события мыши и позволит им
"проходить", чтобы они могли обрабатываться другими элементами внизу.

## MultiPointTouchArea: применение

MultiPointTouchArea можно использовать двумя способами:

*	настройка touchPoints для предоставления объектам точек касания свойств, к которым можно привязаться;
*	использование обработчиков onTouchUpdated или onPressed, onUpdated и onReleased.

В то время как MultiPointTouchArea может принимать исключительное право собственности
на определенные точки касания, также возможно иметь несколько активных MultiPointTouchArea
одновременно, каждый из которых работает на собственном наборе точек касания.

## MultiPointTouchArea: свойства

maximumTouchPoints и minimumTouchPoints содержат диапазон точек касания, обрабатываемых сенсорной областью.
Они позволяют, например, иметь вложенные MultiPointTouchAreas, одну для обработки двух касаний
пальцев, а другую для обработки трех касаний пальцев.
По умолчанию обрабатываются все точки касания в области касания.

Если mouseEnabled имеет значение true, мышь действует как точка касания, поэтому она также
подвержена этим ограничениям: например, если maximumTouchPoints равно двум, вы можете использовать
мышь как одну точку касания и палец как другую точку касания, в общей сложности две точки касания.

touchPoints содержит набор пользовательских объектов точек касания, к которым можно привязаться.
Если mouseEnabled имеет значение true (по умолчанию) и левая кнопка мыши нажата, когда мышь
находится над сенсорной областью, текущая позиция мыши будет одной из этих точек касания.
По умолчанию это свойство содержит пустой список.

## MultiPointTouchArea: пример

В следующем примере у нас есть два небольших прямоугольника,
которые следуют за нашими точками касания.

## MultiPointTouchArea: сигналы [1]

canceled испускается, когда новые события касания были отменены, потому что другой элемент
украл обработку события касания.
Этот сигнал предназначен для расширенного использования: он полезен, когда имеется более одной
MultiPointTouchArea, которая обрабатывает ввод, или когда внутри Flickable есть MultiPointTouchArea.
В последнем случае, если вы выполняете некоторую логику в обработчике сигнала onPressed,
а затем начинаете перетаскивание, Flickable может украсть обработку касания из MultiPointTouchArea.
В этих случаях для сброса логики, когда MultiPointTouchArea утратил сенсорную обработку
для Flickable, сигнал canceled должен быть обработан в дополнение к released.
touchPoints - это список отмененных точек.

pressed испускается, когда добавляются новые точки касания.
touchPoints — это список этих новых точек.
Если для MinimumTouchPoints установлено значение больше единицы, этот сигнал не будет излучаться
до тех пор, пока не будет достигнуто минимальное количество требуемых точек касания.

released испускается при удалении существующих точек касания.
touchPoints — это список удаленных точек.

## MultiPointTouchArea: сигналы [2]

gestureStarted испускается при достижении глобального порога перетаскивания.
Этот сигнал обычно используется, когда MultiPointTouchArea был вложен в Flickable или другую
MultiPointTouchArea.
Когда порог достигнут и сигнал обработан, вы можете определить, должна ли область касания
захватывать текущие точки касания.
По умолчанию они не будут захвачены; чтобы захватить их, вызовите  gesture.grab().
Если жест не захвачен, то, например, вложенный Flickable также будет иметь возможность захватить его.
Объект жеста также включает в себя информацию о текущем наборе touchPoints и dragThreshold.

touchUpdated испускается при изменении точек касания, обрабатываемых MultiPointTouchArea.
Это включает в себя добавление новых точек касания, удаление или отмену предыдущих точек касания,
а также обновление текущих данных точки касания. touchPoints — это список всех текущих точек касания.

updated испускается при обновлении существующих точек касания.
touchPoints — это список обновленных точек.
