Компоненти за бързи най-добри практики на Qt

QML предоставя удобен начин за разбиване на код, наречен „Компоненти“. Най-лесният начин да създадете компонент, който може да се използва повторно по-късно, е да добавите нов файл към работната директория на основния QML файл.

Също така компонентите могат да бъдат пакетирани като модули (Qt Components е такъв модул) и публикувани като добавки. Тази публикация е за използването на компоненти за писане на чист и поддържаем QML код.

Създаване на нови компоненти

Първият пример показа лекотата на създаване на допълнителни компоненти, така че не се страхувайте да ги използвате. Не превръщайте писането на код за многократна употреба във ваш първи приоритет. Стремете се към капсулиране на детайлите на изпълнението и отделяне на компонентите. Компонентите трябва да са малки. Следвайки тези правила, вие автоматично ще стигнете до код, който може да бъде използван повторно по-късно.

Нека да разгледаме този пример за прост аналогов часовник:

Този код съдържа компонент Clock, който при изпълнение изглежда като екранната снимка по-долу. Въпреки факта, че се използва само веднъж в приложението, има смисъл да се отдели от основния файл.

компоненти

Първо, това прави логиката, която остава във файла main.qml, проста и разбираема: таймер, който актуализира часовете, минутите и секундите на компонента Clock, е всичко, което разработчикът трябва да види в main.qml, ако иска да добави функционалност към него.

Второ, нашият часовников компонент не трябва да се тревожи за собствената си позиция в прозореца. Да предположим, че има елемент Row, който използва нашия компонент Clock N пъти. Ако основният елемент на компонента Clock имаше кода'anchors.fill: parent', не бихме могли да използваме неговите екземпляри в елемента Row: всеки екземпляр на Clock ще заеме целия width_row, вместо width_row / N. Ето защо QML забранява използването на повечето котви (котви) в елементи, поставени в елемента Row. Ако искаме нашият компонент Clock да остане многократно използваем, не е нужно да правим много предположения относно бъдещата му употреба. В обобщение, основният елемент на компонент не трябва да съдържа анкери към своя родител или да използва твърдо кодирани мениджъри на оформление.

В същото време компонентът Clock задава фиксирани стойности за своята дължина и ширина. От семантична гледна точка това са размерите по подразбиране на нашия компонент. Те не ограничават използването на нашия компонент, тъй като неговите екземпляри могат да бъдат преоразмерени, ако е необходимо. Компонентите с нулеви размери се считат за невидими елементи, така че задаването на ненулеви размери по подразбиране избягва глупави грешки.

Има и други, по-малко очевидни предимства, като създаването на съставни елементи и капсулирането на детайлите на изпълнението.

Създаването на съставен елемент (да го наречем ComposedElement) от прости елементи ElementA, ElementB и ElementC улеснява добавянето на нови свойства и действия към елементите. Можем да добавяме нови елементи ElementD и ElementE към нашия ComposedElement, без да се налага да променяме ElementA, ElementB или ElementC. Нашите прости елементи са изолирани един от друг и следователно не могат просто да се счупят, ако някой от тях внезапно се промени.

Компонентите могат да бъдат разделени на публични и частни части, точно както в C++ и Java класовете. Публичният API на компонент е сборът от всички негови свойства и методи,дефиниран върху коренния елемент (включително свойства, наследени от него). Това означава, че такива свойства могат да се променят и такива методи могат да се извикват от потребителите на компонента.

Всяко свойство или метод, дефинирани върху вложен елемент (не основния елемент), може да се счита за напълно частен API. Това позволява подробностите за изпълнението да бъдат капсулирани и в крайна сметка трябва да станат обичайни, когато разработчиците създават компоненти.

За да докажем ползата от капсулирането, можем да премахнем вътрешния елемент „impl“ от Clock.qml и да стартираме приложението отново (например чрез „$ qmiviewer main.qml“). Няма да се виждат нови грешки, тъй като публичният API на компонента Clock не е променен. Това означава, че можем свободно да променяме „impl“, знаейки, че няма да има странични ефекти от такива промени за други компоненти.

Можем дори да разширим тази идея и да оставим Clock.qml да зарежда динамично някакъв „impl“ елемент, в зависимост от ситуацията. Това въвежда концепцията за полиморфизъм в QML; прилагането на такъв механизъм е оставено като упражнение на читателя.

Ако имаме добре проектиран, минимален публичен API за всеки компонент, можем да се съсредоточим върху разработването на интерфейси, а не върху конкретни реализации.

Повторно използване на компоненти

Нека да видим дали наистина можем да използваме отново компонента Clock.qml. Той е чудесен за създаване на часовници, които показват световното време. В този случай нямаме нужда от втора ръка за тях. Можем леко да променим поведението на Clock.qml, така че последният да не показва часове, минути или секунди, ако стойността им е по-малка от нула. За елемент на изображение с >

Не сме променили обществения API. Ние също вярваме, че използването на аналогов часовникотрицателни стойности за секунди все още няма смисъл. Ето защо сме уверени, че тази промяна няма да засегне съществуващите приложения, които използват компонента Clock.

В нашия пример за световен часовник можем да покажем местна информация за времето, наред с други неща. Можем да използваме един от наличните API за метеорологични услуги заедно с XmlListModel, който ни позволява декларативно да извличаме данни от API. Таймерът, който преди беше използван само за актуализиране на часа на часовника, сега ще се използва за актуализиране на данните за времето веднъж на час. Забележете как се въвежда сигналът за актуализиране, който е свързан с функцията за актуализиране на данни на XmlListModel.

Модифицираният пример показва световния часовник и местната информация за времето за три града.