Форум программистов, компьютерный форум, киберфорум
Wyn
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

Общий QML

Запись от Wyn размещена 15.04.2016 в 14:30
Показов 8121 Комментарии 10
Метки javascript, qml

Данный цикл статей представляет собой частично FAQ, частично шпаргалку различных костылей и описаний подводных камней, встречаемых при работе с QML. В данную статью постепенно будут заноситься вся подобная платформонезависимая информация о QML. Для специфичных знаний о конкретных платформах - PC, Android и т.д. будут созданы отдельные статьи, на которые будет дана ссылка в конце документа.

Любая конструктивная критика, пожелания и отзывы - приветствуются. Сообщения по поводу орфографических и грамматических ошибок(коих тут много, знаю) лучше кидать в личку. =)

Общий QML

Оглавление
  1. Основы
    1. Правила QML
    2. Свойства и соединения
    3. Динамическое создание объектов
    4. JavaScript
    5. Перевод приложения
  2. Взаимодействие между QML и C++
    1. Основы
      1. Нерегистрируемые в QML объекты
      2. Регистрируемые в QML объекты
    2. Реализация специфичных для QML типов и аттрибутов
      1. Прикреплённые объекты и аннотации
      2. Модификаторы свойств
      3. Определение свойства по-умолчанию для QML-объектов в С++
      4. Получение уведомлений об инициализации объекта
  3. Рекомедации
    1. Общие рекомендации
    2. Оформление кода
    3. Масштабируемость
    4. Оптимизации
  4. Полезности
    1. Общие
      1. Двунаправленное соединение
      2. Скрытые свойства в подключаемом элементе
      3. Неизменяемое снаружи свойство в подключаемом элементе, которое можно изменять внутри
      4. Реализация класса асинхронной загрузки изображений
    2. Работа с компонентами
      1. StackView(controls1)
  5. Специфика платформ(пока нет)
    1. Android
    2. iOS
    3. Linux
    4. Windows
  6. Список ссылок и литературы

Основы

Правила QML
  1. В каждом QML документе есть только один корневой элемент
  2. В каждом QML документе есть как минимум один импорт(import QtQuck x.x)
  3. Каждый QML документ должен начинаться с заглавной буквы(исключение - main.qml)
  4. Название каждого элемента(id) должно начинаться с маленькой буквы


Свойства и соединения

Свойства(property) бывают встроенные в элемент и дополнительные.
Дополнительные свойства объявляются в QML-элементе с помощью:
[default | readonly] property <propertyType> <propertyName>: <binding>
где:
  • [default] - свойство по умолчанию, может быть только одно.
    В подобное свойство элемента записываются любые подэлементы, не относящиеся к какому-либо конкретному свойству.
    Пример
    JavaScript
    1
    2
    3
    4
    5
    
    // MyItem.qml
    import QtQuick 2.0
    Text {
        default property var someItem
    }
    JavaScript
    1
    2
    3
    4
    5
    6
    7
    
    MyLabel {
        Rectangle { id: someRectangle } // автоматически будет записана в someItem
    }
    // будет аналогично 
    MyLabel {
        someItem: Rectangle { id: someRectangle }
    }

  • [readonly] - свойство, которое инициируется только один раз, при создании, и которое в дальнейшем нельзя изменить. Аналог константы.

  • <propertyType>: Тип свойства. Свойства бывают:
    • Простые свойства: bool, int, double, url, string, list (а также color, date, font и т.д.)
      Описание

      По сути дела обычные свойства копируют переменные стандартного C++(точнее - Q_PROPERTY). Они также сигнализируют об изменении их значения.
    • JS свойства: var
      Описание

      Свойство var может хранить в себе всё что угодно. Работа с данным свойством принципиально отличается от работы с остальными свойствами. Фактически данное свойство - это js-переменная, указатель на данные. И сигнал о изменении свойства поступает только при изменении этого самого указателя. Любые данные, изменённые внутри этого свойства, никакого сигнала порождать не будут. Применяя данное свойство нужно учитывать это. Из природы указателя проистекает и другое свойство данного свойства - у двух свойств var, которые имеют общий указатель(то есть ссылаются на одни и теже js-данные), пускай они даже находятся в разных частях программы, всегда будут общие данные(данные изменённые в одном месте, тут же будут доступны в другом). Также следует понимать, что использование этого свойства создаёт гораздо большую нагрузку, тк любая работа с данными в нём выполняется в контексте js.
      Пример
      JavaScript
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      Item {
          property var aNumber: 100
          property var aBool: false
          property var aString: "Hello world!"
          property var anotherString: String("#FF008800")
          property var aColor: Qt.rgba(0.2, 0.3, 0.4, 0.5)
          property var aRect: Qt.rect(10, 10, 10, 10)
          property var aPoint: Qt.point(10, 10)
          property var aSize: Qt.size(10, 10)
          property var aVector3d: Qt.vector3d(100, 100, 100)
          property var anArray: [1, 2, 3, "four", "five", (function() { return "six"; })]
          property var anObject: { "foo": 10, "bar": 20 }
          property var aFunction: (function() { return "one"; })
      }

    • Объектные свойства - унаследованные от QtObject.
    • alias - перенаправляет любые действия с этого свойства на другое, указанное в binding. Фактически это виртуальное свойство, созданное исключительно ради того, чтобы дать доступ к другому свойству.

  • <propertyName> - имя свойства, должно начинаться с маленькой буквы и может состоять только из букв, цифр и знака подчёркивания _. Также в качестве имени запрещено использовать ключевые слова js.

  • <binding> - связанное с свойством соединение, которое инициирует и изменяет свойство. В случае отсутствия свойство инициируется состоянием undefined.
Свойства быть объявлены и на стороне С++ с помощью макроса Q_PROPERTY. Подробнее ниже, в разделе "Взаимодействие между QML и C++".


При создании любого QML-свойства автоматически создаётся сигнал <propertyName>Changed, вызываемый каждый раз, когда свойство изменяется, и связанный с сигналом обработчик on<propertyName>Changed (Учтите, что тут <propertyName> будет начинаться с большой буквы), в котором можно обработать изменение свойства.
Пример

JavaScript
1
2
3
4
5
Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("Следующий цвет будет: " + nextColor.toString())
}


Изменение свойств осуществляется двумя способами:
  1. При их создании с помощью статичного значения или выражения-привязки <propertyName> : <value>
    Выражение-привязка представляет собой js выражение, которое описывает зависимость значения данного "привязанного" свойства от других. Данные другие свойства в этом выражении называются "зависимостями". Движок QML следит за этими "зависимостями" и при изменении любой из "зависимостей" инициирует вычисление нового значения выражения-привязки, которое затем присваивает "привязанному" свойству.
    Пример инициализации свойства статичным значением и выражением-привязкой
    JavaScript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    import QtQuick 2.0
     
    Rectangle {
        // Оба этих свойства инициируются статичным значением
        width: 400
        height: 200
     
        Rectangle {
            // Оба этих свойства инициируются выражением-привязкой
            width: parent.width / 2   // свойство width будет изменяться всякий раз при изменении аналогичного свойства у родительского элемента 
            height: parent.height
        }
    }

  2. В js присваиванием [<objectId>.]<propertyName> = value
    Пример
    JavaScript
    1
    2
    3
    4
    5
    6
    7
    8
    
    import QtQuick 2.0
     
    Rectangle {
        id: rect
        Component.onCompleted: {
            rect.color = "red" // изменение значения уже созданного свойства
        }
    }

  3. Через дополнительные средства. К примеру через QML-элемент Binding, который делает неубираемую привязку, существующую даже в случае js-присваиваний.


Динамическое создание объектов

Динамическое создание объектов в QML обычно востребовано по двум разным причинам:
  1. для уменьшения потребления памяти
  2. для большей плавности и отзывчивости интерфейса
Пример создания динамического самоудаляемого элемента на примере Dialog
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import QtQuick.Dialogs 1.2
...
id: root
...
Button {
    id: saveDialogButton
 
    text: "Save Dialog"
 
    onClicked: {
        var svDialog = saveDialogComponent.createObject(root)
        svDialog.text = text
        svDialog.save.connect(function(){ fileio.saveCurrent(); }) // учтите, что функция будет вызываться в контексте где она объявлена,         
                                                                                        // а не в контексте svDialog.
// К сожалению, почему-то нельзя данным образом присоединить сигнал изменения свойств(<свойство>Changed).
// Поэтому saveDialog приходится создавать в качестве компонента(чтобы прописать там самоудаление)
 
        svDialog.open()
    }
}
 
Component {
    id: saveDialogComponent
 
    Dialog {
        id: saveDialog
 
        signal save
 
        standardButtons: StandardButton.Save | StandardButton.Cancel
 
        onClickedButtonChanged: if (StandardButton === StandardButton.Save) save()
        onVisibleChanged: if (visible === false) destroy() // автоматическое уничтожение компонента при его сокрытии
    }
}

Также существует элемент Loader, который может динамически загружать элементы и файлы QML.


JavaScript

Есть собственно два типа js файлов в qml - обычные и библиотеки. Обычные файлы JS при подключении в qml создаются и выполняются в пространстве имён подключённого qml файла. Библиотеки содержат в себе объявление .pragma library. Они имеют своё собственное пространство имён и создаются только один раз.
Подключать другие файлы js из js файлов можно с помощью .import "файл.js".


Перевод приложения

http://doc.qt.io/qt-5/qtquick-... ation.html
Маркировка строк перевода в QML осуществляется в основном с помощью функции qsTr(text)(есть и дополнительные функции вида "qsTr..." - смотрите по ссылке).
JavaScript
1
2
3
4
5
6
7
Text {
    id: txt1
    // Обычная строка комментария
    //: Основная строка, комментирующая перевод
    //~ Опциональная строка, которая предоставляет дополнительные данные для перевода
    text: qsTr("Back");
}
Рекомендации:
  1. Документация Qt настоятельно рекомендует не разделять строки(пример: text: "page: "+pageNumber+", words count: "+wordsCount), а использовать .arg() (пример: text: "page: %1, words count: %L2".arg(pageNumber).arg(wordsCount)).

  2. Использовать %L, чтобы представлять числа в соответствии с теми нормами, которые применяются в регионе. К примеру text: qsTr("%L1").arg(total) // total=4321.56 будет отображаться как 4,321.56 в английском регионе и как 4.321,56 в немецком.

  3. Использовать Qt.locale(), который представляет собой информационный класс о региональных настройках. Пример text:
    qsTr("Date %1").arg(Date().toLocaleString(Qt.locale())) выведет дату в региональном представлении. Также можно локализовывать представления чисел, валюты, дат и времени.
    Также Qt.locale() можно использовать, чтобы загружать данные в зависимости от выбранной локали:
    JavaScript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    Component.onCompleted: {
        switch (Qt.locale().name.substring(0,2)) {
            case "en":   // показать иконку английского языка
                languageIcon = "../images/language-icon_en.png";
                break;
            case "fi":   // показать иконку финского языка
                languageIcon = "../images/language-icon_fi.png";
                break;
            default:     // показать стандартную иконку языка
                languageIcon = "../images/language-icon_default.png";
        }
    }
  4. Использовать QT_TR_NOOP при переводах строк, хранящихся в массивах и моделях. Пример:
    JavaScript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ListModel {
        id: myListModel;
        ListElement {
            //: Capital city of Finland
            name: QT_TR_NOOP("Helsinki");
            }
        }
     
    ...
     
    Text {
        text: qsTr(myListModel.get(0).name); // получить перевод свойства name нулевого элемента модели myListModel
        }

Ну и куда же без костылей, приберёг их на последок:
lupdate, к сожалению, проверяет в проекте файлы только в списках SOURCES и HEADERS. Это значит, что файлы расположенные в других списках, а также в ресурсах, останутся без его внимания. Поэтому применяют костыль в виде lupdate_only:
JavaScript
1
2
3
4
5
6
lupdate_only{
SOURCES = *.qml \
          *.js \
          content/*.qml \
          content/*.js
}
Данное дополнение списка SOURCES будет видно только для lupdate.

Действия при переводе - стандартные:
  1. Задаёте в проекте файлы перевода ts:
    Code
    1
    2
    
    TRANSLATIONS = name_en.ts \
                   name_ru.ts
  2. Вызываете lupdate. Удостоверяетесь, что ошибок при генерировании/обновлении файлов ts не было.
  3. Запускаете Linguist, переводите данные файлы.
  4. Запускаете lrelease и генерируете конечные файлы перевода *.qm
Метки javascript, qml
Размещено в Qt, QML
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 10
Комментарии
  1. Старый комментарий
    Аватар для Avazart
    Почему "Переменные" ? Свойства.
    Запись от Avazart размещена 16.04.2016 в 11:04 Avazart вне форума
  2. Старый комментарий
    Аватар для Wyn
    Цитата Сообщение от Avazart
    Почему "Переменные" ? Свойства.
    Моешь назвать это спорным решением. Я посчитал что "переменные" будут более понятны для тех, кто придёт из С++ в QML. Я ещё размышляю над тем, было ли это решение верным. Возможно в следующем редактировании заменю "переменные" на "свойства".
    Запись от Wyn размещена 17.04.2016 в 15:49 Wyn вне форума
  3. Старый комментарий
    Аватар для Avazart
    Моешь назвать это спорным решением.
    Ошибочным переводом, не более. Переменная и свойство это разные вещи.
    Приведите хотя бы одну книгу где свойства в контексте Qt называю переменными.

    посчитал что "переменные" будут более понятны для тех, кто придёт из С++ в QML.
    Ну давайте тогда что бы совсем было понятно будем называть это просто "фиговиной" ?

    Переменная - это именованная область памяти.
    Свойство - способ доступа к внутреннему состоянию объекта, имитирующий переменную некоторого типа.

    https://ru.wikipedia.org/wiki/... 8%D0%B5%29
    https://ru.wikipedia.org/wiki/... 8%D0%B5%29
    Запись от Avazart размещена 18.04.2016 в 22:07 Avazart вне форума
  4. Старый комментарий
    Аватар для Wyn
    Цитата Сообщение от Avazart
    Свойство - способ доступа к внутреннему состоянию объекта, имитирующий переменную некоторого типа.

    https://ru.wikipedia.org/wiki/... 8%D0%B5%29
    Понял. Исправлю на свойство в следующей версии.
    Кстати, какими-нибудь особенными советами по оптимизации можешь поделиться?
    Запись от Wyn размещена 26.04.2016 в 21:38 Wyn вне форума
  5. Старый комментарий
    Кстати в контексте QML все же одно из главных понятий это не свойства (или переменные), а атрибуты. Свойство это всего лишь один из типов атрибутов...

    The set of QML object-type attribute types is as follows:
    • the id attribute
    • property attributes
    • signal attributes
    • signal handler attributes
    • method attributes
    • attached properties and attached signal handler attributes
    Запись от pav1uxa размещена 08.05.2016 в 10:53 pav1uxa вне форума
  6. Старый комментарий
    Аватар для Avazart
    Цитата Сообщение от Wyn
    Кстати, какими-нибудь особенными советами по оптимизации можешь поделиться?
    Оптимизации чего?
    Цитата Сообщение от pav1uxa
    Кстати в контексте QML все же одно из главных понятий это не свойства (или переменные)
    Тут скорее контекст С++Qt, в С++Qt свойства используются для того что бы состояние объекта было видимо и доступно из вне, в данном случае из QML
    (так же используется для доступа из QScript/QJSEngine и главное для того что бы можно было редактировать виджеты визуально в дизайнере форм)

    В скриптах же "свойства" менее выражены ибо нет такой необходимости ибо обычно отсутствуют модификаторы доступа.
    C QML дела чуть сложнее ибо он заточен на взаимодействие С++Qt и нужно дергать сигналы/слоты.
    Запись от Avazart размещена 08.05.2016 в 12:13 Avazart вне форума
  7. Старый комментарий
    Цитата Сообщение от Avazart
    Тут скорее контекст С++Qt, в С++Qt свойства используются для того что бы состояние объекта было видимо и доступно из вне, в данном случае из QML
    (так же используется для доступа из QScript/QJSEngine и главное для того что бы можно было редактировать виджиты визуально в дизайнере форм)
    Да, но я имею ввиду в общем смысле. Статья то называется QML. Было бы неплохо упомянуть про атрибуты и какие они бывают...
    Запись от pav1uxa размещена 08.05.2016 в 12:20 pav1uxa вне форума
  8. Старый комментарий
    Аватар для Avazart
    Цитата Сообщение от pav1uxa
    Было бы неплохо упомянуть про атрибуты и какие они бывают...
    Думаю да, не помешало бы, но тогда бы вероятно пришлось бы пересказывать все что в документации
    Запись от Avazart размещена 08.05.2016 в 12:39 Avazart вне форума
  9. Старый комментарий
    Аватар для Wyn
    Цитата Сообщение от pav1uxa
    Кстати в контексте QML все же одно из главных понятий это не свойства (или переменные), а атрибуты. Свойство это всего лишь один из типов атрибутов...
    Не отрицаю. Но если подходить к теме с этой стороны, то там очень много переводить надо. Пока что времени на это нет, в свободное время сейчас пытаюсь сделать элемент Callout по аналогии с Rectagnle. Как его доделаю и время появится - переработаю и дополню статью.
    Цитата Сообщение от Avazart
    Оптимизации чего?
    Оптимизации, наблюдения по поведению(подводные камни) QML и QML-обвязки, может ссылки какие-нибудь интересные по теме, которые попались в работе. Это наиболее интересно. Вот я, к примеру, замечал, что autoscale из Qt 5.6 применительно к Image в Android 5 не применяется, а в Android 6 - применяется. Хочется статью по этой теме написать, но материала по подобным подводным камням пока очень мало.
    Запись от Wyn размещена 20.05.2016 в 13:56 Wyn вне форума
  10. Старый комментарий
    Аватар для Avazart
    Нет я попробовал QML понял что оно еще сырое - уткнулся что толком MVC не реализовано - нет табличного представления, и забросил его изучение.
    Запись от Avazart размещена 20.05.2016 в 16:05 Avazart вне форума
 
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru