Добро пожаловать в руководство по Qt Design Studio Sketch Bridge. Чтобы следовать ему, вам понадобятся коммерческий пакет Qt Design Studio 1.5 и Sketch Bridge, macOS и Sketch (разработчик использует 66.1).
В этом уроке будет рассказано, как сделать sketch-проект, который создает чистый экспорт и импорт в Qt Design Studio (сокращенно будем называть qds для остальной части урока), использует символы и экземпляры для правильной компонентизации и переходит от Sketch к qds в итеративных циклах, создавая более сложную сцену из простых строительных блоков. Также расскажем о некоторых наиболее распространенных проблемах, с которыми сталкиваются пользователи, дадим советы и хитрости, которые разработчик создал, работая с плагином Bridge.
Прежде чем начнутся дальнейшие разъяснения отметим, что, хотя Sketch позволяет дизайнерам гибко и открыто реализовывать свои концепции дизайна, для создания идеального по пикселям дизайна, построенного на дружественных для разработчика компонентах в qds, очень важно структурировать и подготовить свой проект определенным образом и, хотя его освоение не слишком сложно, для его успешного выполнения требуются время и знания. Разработчики надеются, что это руководство предоставит вам необходимые знания, чтобы приблизить ваши проекты к желаемому вами результату. Давайте углубимся и начнем проектировать.
Часть 1.1 - Простая кнопка
Первый шаг начнётся с разработки единственной кнопки, которая будет использоваться в качестве основы для проекта и запустить его в Sketch, поэтому откройте приложение Sketch и создайте новый пустой файл.
Сначала давайте создадим фон кнопки по умолчанию, перетаскивая прямоугольник. Стоит убедиться, что это правильный размер для кнопки, затем превратить его в символ. После того как создали символ, давайте удалим экземпляр и будем работать напрямую на главном символе.
Затем можно добавить несколько хорошо закругленных углов, создать градиент, добавить тень и подсветку к кнопке. Чтобы сделать дизайн более легким, можно немного растянуть артборд, чтобы освободить место для теней и добавить рабочий фон для символа. Давайте выберем цвет, который не планируется использовать в дизайне, но который дает сильный контраст с цветами дизайна, как этот бледно-розовый на видео ниже.
Кроме того, хотя выбор этих двух параметров был отменен, не нужно, чтобы этот фон экспортировался или появлялся, когда символы позже будут использоваться. С размеченным пространством дизайна давайте закруглим эти углы, добавим простой градиент и несколько теней.
Теперь имеется фоновое состояние по умолчанию для кнопки, поэтому давайте создадим два других состояния, которые хотелось бы использовать для этого урока - состояние наведения и нажатия (hover and pressed state) .
Сделать это можно, продублировав оригинальный прямоугольник, переименовав слои, а затем разместив их рядом, чтобы можно было видеть параллельные изменения дизайна. Дабы сделать это немного проще, растянем ширину символа, чтобы он соответствовал кнопке рядом, изменим размер после того, как закончим с дизайном.
Теперь имеется хорошая настройка, поэтому давайте изменим версии наведения и нажатия фона кнопки, слегка корректируя цвета градиента, пока не получим три версии кнопки. Хотя в UX нет настоящих правил, которые можно считать актуальными, до тех пор, пока эти состояния согласованы и работают с вашим общим дизайном пользовательского интерфейса, разработчики придерживаются логики, что состояние наведения немного ярче, чем нормальное, а нажатое состояние немного темнее.
На этом этапе разработчики также дадут название своим слоям и будут использовать эти имена и для идентификаторов qml, но вскоре это будет рассмотрено более подробно.
С тремя ранее созданными фонами, давайте поместим их обратно друг на друга, так как желаем, чтобы они были такими же для экспорта, и добавим еще один элемент, который сделаем верхним слоем – точку доступа (hotspot) , которая при импорте в design studio будет автоматически преобразована в область мыши.
Важно, что, когда добавляем точку доступа, чтобы установить цель в none, нужно быть уверенным, что это верхний слой кнопки, чтобы правильно захватывать события мышкой.
Также стоит убедиться, что артборд с кнопкой на нем достаточно большой, чтобы вместить все эффекты тени, которые были добавлены без обрезки, но подобрались достаточно близко к границам, чтобы убедиться, что ограничивающая рамка элемента не слишком большая. Хорошо и плотно прилегающие к границам эффекты работают лучше всего.
После всех предыдущих шагов имеется простая кнопка для подготовки настроек в плагине Qt Bridge.
Наиболее распространенные ошибки, которые видят разработчики у пользователей, использующих sketch bridge, происходят из-за наличия дублирующих идентификаторов в их проекте, хотя импортер в qds способен обнаруживать и сохранять идентификаторы qml, все же рекомендуется вручную проверить все идентификаторы qml, чтобы убедиться, что они являются уникальными и значимыми.
Одна из проблем заключается в том, что после переименования идентификатора qml для символа каждый экземпляр этого символа будет иметь повторяющийся идентификатор. Совет разработчика заключается в использовании схемы именования, которая различает символ и экземпляры этого символа.
Например, удостоверимся, что ваш символ кнопки имеет идентификатор myButton_Symbol, а разные слои имеют этот префикс с присоединенными состояниями, как myButton_Symbol_default и т. д. И поскольку, наверняка, будет больше областей мыши, позже в этом проекте можно переименовать точку доступа в myButton_Symbol_hotspot, когда будем использовать кнопку в качестве экземпляров на экране, обязательно дадим этим экземплярам уникальный идентификатор, связанный с этим экраном, а также импортируем, чтобы отметить, что идентификаторы qml могут использовать только подмножество возможных символов. Для этого в руководстве будут использоваться подчеркивания, чтобы отделить имена, так как хорошо известно, что этот формат будет работать.
Когда переименовали эти идентификаторы, стоит убедиться, что все слои установлены в Child, так как желательно, чтобы для каждого слоя были отдельные asset’ы, поэтому не будем ничего объединять на данном этапе. Позже, когда создадим некоторые фоны, будем использовать объединение, чтобы минимизировать количество отдельных asset’ов в дизайне, но сейчас давайте правильно установим все эти qml-идентификаторы и убедимся, что для каждого из дизайнов кнопок установлен тип экспорта child.
По субъективному опыту разработчика, имеет смысл называть слои точно так же, как ваши идентификаторы qml, это значительно облегчит поиск иллюстраций позже, особенно потому, что эти файлы могут стать очень большими и сложными, когда они приближаются к уровню завершения проекта пользовательского интерфейса.
В плагине Qt Bridge стоит сначала настроить несколько основных свойств на странице настроек. Это глобальные настройки, которые будут использоваться для остальной части проекта, поэтому нужно будет сделать это только один раз. Сначала необходимо выбрать путь экспорта. Для этого создадим папку проекта, где позже сможем создать проект Design Studio, в которой создадим папку экспорта и выберем ее в качестве местоположения, в которое хотим поместить asset’ы и метаданные. Создайте необходимые папки с помощью сочетания клавиш shift+cmd+n.
Оставим все остальные настройки по умолчанию и будем использовать png для этого урока. На данный момент все готово, чтобы вернуться к домашней панели Bridge Plugin и выполнить первый экспорт.
Со всеми qml-идентификаторами и типами экспорта, установленными правильно, вы готовы экспортировать компонент и перенести его в Design Studio, где добавим несколько состояний и протестируем кнопку, прежде чем продолжим разработку в Sketch.
Итак, давайте просто нажмем на экспорт, а затем отправимся в Design Studio.
Часть 1.2 - Первый импорт
Для начала в Design Studio можно создать пустой проект для импорта Sketch design, поэтому давайте перейдем на домашнюю страницу и нажмем кнопку нового проекта, это запустит wizard (мастера), после чего нужно выбрать пустой проект по умолчанию.
Можно выбрать папку проекта в качестве местоположения для этого проекта, а затем остальные параметры можно оставить по умолчанию. После завершения работы wizard последует автоматическое переключение на файл ui.qml по умолчанию, который поставляется вместе с проектом, чтобы импортировать sketch design, теперь можно перейти на панель asset’ов, добавить новые asset’ы и затем перейти к папке, в которую экспортировали проекты из Sketch.
Далее нужен .metadata file. Это опция будет доступна, только если у вас есть коммерческая версия Design Studio с включенным плагином средства импорта.
Чтобы проверить это, вы можете посмотреть доступные импорты в поле со списком фильтров типов файлов. Если тип метаданных (metadata type) есть, значит у вас имеется корректная настройка, и можно выбрать этот файл, чтобы запустить панель импорта.
Для первого импорта следует использовать настройки по умолчанию, далее экспортировать метаданные и asset’ы, оставляя слияние отключенным. Но, поскольку, хочется сразу же начать работу над некоторыми вещами в Design Studio, при всех последующих импортах оставим функцию слияния включенной, поэтому случайно не перезапишите вашу работу в qds.
После завершения импорта можно закрыть импортер и взглянуть на импортированные файлы. Они будут расположены в папке с именем вашей папки экспорта. Если перейдёте в эту папку, то увидите элементы. На данный момент у вас есть только один компонент кнопки, поэтому давайте перейдем к этому файлу и проверим, что ваш экспорт выполнен правильно.
В этом файле должны быть три разных слоя кнопок, которые будут использоваться для разных состояний плюс область мыши. По умолчанию sketch прикрепляет пустой слой к экспорту, здесь он называется asset’ом, и первое, что нужно сделать сейчас - это удалить этот слой, так как он не нужен в вашем компоненте.
После этого вам нужно установить, чтобы область мыши наведения была включена, поскольку будет использоваться состояние наведения. Давайте сделаем это прямо сейчас, щелкнув мышью на области мыши в навигаторе, перейдя на панель свойств и выбрав наведение мышью для вашей области мыши.
Поскольку в настоящее время находимся в Base State (базовом состоянии), это единственное состоянии, которое имеем на данный момент, поэтому оно будет применяться к каждому состоянию, которое будет добавляться с этого момента. Пока вы здесь, вы можете добавлять нужные вам состояния. Вы всегда должны пытаться использовать явные пользовательские состояния для приложения.
Базовое состояние полезно для внесения изменений в ваш дизайн, который желаем применить к любому другому состоянию, если в настоящее время находимся в состоянии, созданном пользователем, то любые изменения, которые мы вносим в текущем состоянии будут применяться только к этому состоянию.
Итак, давайте создадим три состояния, которые вам нужны для этой кнопки. Добавим состояние с именем по умолчанию, одно с именем наведения, а другое - с нажатием.
Теперь у вас есть эти состояния, можно изменить состояние системы по умолчанию на пользовательское состояние по умолчанию. Делаем это, щелкая иконку действия на миниатюре состояния и выбирая «сделать по умолчанию» (“make default”), теперь каждый раз при загрузке этого компонента - это будет состояние, в котором видна кнопка.
Теперь необходимо добавить некоторую логику в эти состояния, чтобы соединить их с вашей областью мыши. Сделаем это на следующем шаге, используя параметр, когда условия выбора также будет здесь на иконке действия (action icon). А пока давайте подготовим иллюстрацию в каждом из соответствующих состояний и, поскольку, это первый импорт, давайте начнем с простого показа корректного соответствующего слоя asset’ов в каждом состоянии.
Самый простой способ сделать это - просто сделать соответствующий слой видимым, а все остальные слои невидимыми в каждом состоянии. Итак, сначала давайте вернемся к состоянию по умолчанию, щелкнув по нужной миниатюре на панели состояний. С этим выбранным состоянием можно перейти к вашим изображениям в навигаторе и выбрать каждый из asset’ов один за другим и правильно переключать видимость для каждого слоя, поэтому для состояния по умолчанию нужно, чтобы слой по умолчанию был видимым, а при наведении и нажатии установить невидимым.
После того, как они настроены, можно перейти в состояние наведения и повторить этот процесс, делая изображение при наведении мышью единственным видимым слоем. Наконец, делаем это еще раз для слоя нажатия, выбирая состояние нажатия и повторяя процесс, чтобы сделать видимым только слой нажатия.
Часть 1.3 — Условия выполнения
Теперь вы должны быть готовы добавить логику к этим состояниям, чтобы соединить их с вашей областью мыши, но сначала стоит быстро проверить, что все настроено правильно, щелкая между миниатюрами состояний. Если все правильно, вы должны увидеть только соответствующий слой в редакторе форм (form editor). Предполагая, что все работает нормально, давайте пойдем и добавим логику к состояниям/области мыши, сделаем это с помощью “Условий выполнения”- по сути, это означает, что при выполнении определенных условий это состояние будет активным. Условия выполнения могут усложняться довольно быстро и часто, вам нужно добавить более одного условия, чтобы правильно смоделировать любое значимое поведение. Вы увидите, что в двух состояниях нужно оценить два отдельных условия, чтобы убедиться, что поведение корректно. Также нужно быть осторожными, чтобы проверить, являются ли все проверяемые условия true или not true.
В контексте qml и qds это означает, что возможно оценить достоверность свойств нескольких элементов и переместить пользовательский интерфейс в состояние, в котором применяются эти условия. Можно посмотреть является ли что-то истинным, не истинным, большим, равным и т. д. Также можно сравнить несколько элементов на предмет их достоверности с такими операторами, как AND или OR.
Условия выполнения оцениваются слева направо и в порядке появления в коде, поэтому, если у вас есть два условия для разных состояний, которые оба являются истинными, он выберет первое из этих условий, которое будет применяться к вашему состоянию. Поэтому важно убедиться, что каждое условие может быть истинным только в одном состоянии.
Если в данный момент все это звучит несколько сложно, просто попробуйте следовать шаг за шагом, возможно, к концу у вас создастся лучшее представление о полезности и силе условий выполнения .
Давайте начнем с добавления условия по умолчанию (default condition). Необходимо убедиться, что ваша кнопка по умолчанию отображается, когда мышь не наведена на кнопку и кнопка мыши не нажата. Оба эти условия должны быть условием «не», и оба должны быть истинными, поэтому мышь не наведена и кнопка не нажата - это верное утверждение.
Можно определить условие не выполнения, добавив восклицательный знак перед нашими условиями и для оценки обоих условий будем использовать символ двойного амперсанда между ними. Итак, давайте идти вперед и делать это прямо сейчас. Начните с выбора состояния по умолчанию на панели предварительного просмотра миниатюр состояний, затем щелкните иконку действия и выберите параметр “add when condition” («Добавить при условии»), при этом откроется редактор привязки, и тогда можно добавить ваше условие сюда.
Очень важно, чтобы условие было написано правильно, поэтому будем использовать функцию автозаполнения, чтобы убедиться в отсутствии орфографических ошибок.
Условие состояния по умолчанию (Default State Condition)
После первых трех букв элемента, которые нужно проверить, в данном случае это область мыши, называемая myButton_Symbol_mouseArea. После того, как первые три символа введены, должен быть список всех возможных завершений, поэтому давайте выберем область мыши из списка. В этом первом условии нужно проверить свойство области мыши, которое называется containsMouse.
Это скажет вам, если пользователь навёл на кнопку. Таким образом, после того, как у вас есть область мыши в редакторе привязок, можно добавить точку полной остановки, а затем пройти по списку и найти свойство содержащее мышь и выбрать его.
Теперь имеется первое условие, которое проверяет, что пользователь в данный момент не навёл на кнопку, и это выглядит так:
!myButton_Symbol_mouseArea.containsMouse
Также нужно оценить второе условие, чтобы убедиться, что пользователь также не нажимает кнопку, можно установить условие для оценки обеих вещей, добавив два амперсанда между ними. Теперь можно повторить первый шаг, так как стоит еще раз проверить эту область мыши.
Далее следуют первые буквы области мыши, что вызывает список автозаполнения. Снова выберите область мыши и добавьте точку полной остановки, чтобы получить список свойств, на этот раз интересующее нас свойство является нажатием, которое сообщает нам, содержит ли эта кнопка нажатую мышь.
Итак, окончательное условие для этой первой кнопки должно выглядеть так:
!myButton_Symbol_mouseArea.containsMouse && !myButton_mouseArea.pressed
Само по себе, когда это условие не актуально, то оно ничего и не делает, просто гарантирует, что после того, как событие наведения или нажатия прошло, кнопка вернется в состояние по умолчанию. Поскольку на данный момент кнопка всегда запускается в состоянии по умолчанию не будет видно никаких изменений, поэтому давайте добавим следующие условия, а затем можно проверить кнопку.
Условие состояния наведения (Hover State Condition)
Второе условие должно быть для вашей кнопки наведения, поэтому давайте сначала убедимся, что перешли в правильное состояние, щелкнув миниатюру состояния наведения на панели миниатюр, а затем, получив правильное состояние в редакторе форм, можно добавить следующее. В этом случае нужно, чтобы было состояние наведения, когда мышь находится над областью мыши, но также не нажата (так как это будет нажатое состояние).
Итак, давайте снова запустим редактор привязок для этого состояния, щелкнув иконку действия и выбрав «add when condition» («добавить при условии»). С открытым редактором привязок можно использовать функцию автозаполнения, чтобы убедиться, что условие написано правильно. Первое условие, которое нам нужно, это то, которое проверяет, находится ли мышь над областью мыши, поэтому снова ищем
myButton_Symbol_mouseArea
Когда введем первые три буквы и получим список элементов, доступных в файле, можно прокрутить вниз и выбрать область мыши. Как только выбрали, добавляем точку остановки до конца и запускаем список доступных свойств для оценки.
Свойство, которое нужно называется containsMouse, поэтому можно либо начать печатать, чтобы сузить список, либо прокрутить вниз и выбрать его, заметьте, что на этот раз не добавлен восклицательный знак, потому что хотим проверить, выполняется ли условие и восклицательный знак проверяет, является ли оно ложным. Итак, имеется первое условие для этого состояния:
myButton_Symbol_mouseArea.containsMouse
Также нужно убедиться, что состояние наведения не отображается, когда нажимаем кнопку, так как, чтобы нажать кнопку, мышь должна находиться в области мыши. Чтобы различать эти два события, добавим еще одно условие к состоянию.
Открыв редактор привязки, можно добавить &&, а затем начать добавлять другое условие. В этом случае это то же самое второе условие, что и в предыдущем состоянии по умолчанию. Начиная с восклицательного знака, можно снова ввести условие !myButton_mouseArea.pressed, проверив, что кнопка не нажата.
Итак, теперь у вас должно быть полное условие для этого состояния, и оно должно выглядеть так:
myButton_mouseArea.containsMouse && !myButton_mouseArea.pressed
Первое проверяет то, что мышь находится над кнопкой, но еще не нажата. Как вы можете видеть, единственное отличие - это восклицательный знак в начале, поэтому необходимо тщательно проверять все условия, чтобы убедиться, что всё правильно оформлено.
Давайте добавим окончательное условие, а затем можно протестировать кнопку, и разработчик даст совет, который поможет при отладке более сложных состояний и условий.
Условие состояние нажатия (Pressed State Condition)
Итак, последнее условие для нажатого состояния проще-простого, так как единственное, что необходимо оценить это то, нажата кнопка или нет. Давайте перейдем в нажатое состояние, снова щелкнув по миниатюре на панели состояний, запустим редактор привязок с помощью иконки действия и на этот раз нужно простое условие:
myButton_mouseArea.pressed
Теперь во всех состояниях есть условия, которые можно было бы протестировать с помощью этой кнопки, выполнив предварительный просмотр в реальном времени. В этом случае довольно просто увидеть, активированы ли правильные состояния в нужное время, однако, чем сложнее ваш дизайн и чем тоньше изменения, тем труднее становится. Вы увидите это просто посмотрев превью. Итак, давайте воспользуемся небольшим фокусом, чтобы убедиться, что находимся в правильном состоянии.
Во-первых, для этого нужно убедиться, что вы находитесь в базовом состоянии. Вам нужно добавить метку, которая будет показывать текущее состояние, в котором вы находитесь, поэтому метка и привязка, которые будут использоваться, должны быть в каждом состоянии и иметь правильный способ обработки. Чтобы перейти в базовое состояние, щелкните его на панели состояний, затем перейдите в раздел Qt-Quick Basics в библиотеке типов QML (QML Types library) и перетащите текстовый элемент в редактор форм в верхней части вашей кнопки.
Нужно будет её удалить, как только убедитесь, что состояния правильные, поэтому не имеет большого значения, как она выглядит, пока она читабельна. Поэтому, если вам нужно отрегулировать размер и цвет, чтобы метка была удобочитаемой, сделайте это сейчас.
Как только метка будет готова, нужно будет добавить привязку, поэтому давайте удостоверимся, что текстовый элемент выбран, и затем можно перейти к панели свойств и найти свойство текста для этого элемента.
Теперь наведите на него курсор мыши, чтобы отобразить иконку действия, и запустите редактор привязок, выбрав «установить привязку» («set binding»). Здесь будем использовать эту текстовую метку, чтобы показать текущее состояние компонента. что можно сделать, связав свойство состояния компонента с вашим текстом. Это можно сделать, используя поля со списком в редакторе привязок, это альтернативный более простой способ добавить привязку.
Итак, давайте используем левое поле со списком, чтобы выбрать кнопку myButton_Symbol, а затем правое поле со списком, чтобы выбрать свойство состояния (state property), которое автоматически создаст привязку:
myButton_Symbol.state
Теперь вы должны увидеть, что для всех ваших определенных состояний на метке будет отображаться название состояния. Можно щелкнуть по миниатюрам, чтобы убедиться, что метка верна в каждом состоянии, а затем проверить вашу кнопку, чтобы убедиться, что она работает правильно.
Делается это так, запускается предварительный просмотр в реальном времени с помощью кнопки предварительного просмотра в верхней панели инструментов, при этом кнопка запускается в окне, где можно взаимодействовать с ней. Поэтому нажмите кнопку, которая теперь должна начинаться с состояния по умолчанию, перемещение и выключение мыши должно переключить состояние со стандартного на наведение и обратно, и нажать кнопку мыши, чтобы перемещаться между наведением и нажатием. Вы должны увидеть правильное изображение и метку в каждом штате. Если это работает, поздравляем! Вы создали свой первый правильный компонент qds.
Если это не работает, есть несколько вещей, которые нужно проверить:
Убедитесь, что свойство наведения мыши на область мыши имеет значение true в базовом состоянии и во всех других пользовательских состояниях.
Внимательно проверьте ваши условия на наличие орфографических ошибок.
Если все это правильно, у вас должна быть работающая кнопка. Ниже опубликован код для примера, если вы хотите дважды проверить, совпадает ли ваш.
В следующей части вернемся в Sketch и будем использовать эту кнопку для создания символа меню, состоящего из нескольких экземпляров кнопки, а затем перенести всё обратно в Qt Design Studio для дальнейшей разработки проекта.
Для тех, кто интересуется, как выглядит qml- код:
import QtQuick 2.8 Item { id: myButton_Symbol width: 211 height: 211 state: "default" Image { id: myButton_Symbol_default x: 0 y: 0 source: "assets/myButton_Symbol_default.png" } Image { id: myButton_Symbol_hover x: 0 y: 0 source: "assets/myButton_Symbol_hover.png" } Image { id: myButton_Symbol_pressed x: 0 y: 0 source: "assets/myButton_Symbol_pressed.png" } MouseArea { id: myButton_Symbol_MouseArea x: 0 y: 0 width: 211 height: 211 hoverEnabled: true } states: [ State { name: "default" when: !myButton_Symbol_MouseArea.containsMouse && !myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_hover visible: false } PropertyChanges { target: myButton_Symbol_pressed visible: false } }, State { name: "hover" when: myButton_Symbol_MouseArea.containsMouse && !myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_pressed visible: false } PropertyChanges { target: myButton_Symbol_default visible: false } }, State { name: "pressed" when: myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_default visible: false } PropertyChanges { target: myButton_Symbol_hover visible: false } } ] }