36,3
рейтинг
15 ноября 2009 в 22:14

Разработка → QML — новый подход к построению GUI

Qt*
Традиционно все десктопные приложения пишутся на императивных языках программирования, этот подход прост и понятен, куда проще описать последовательность действий для решения той или иной задачи, нежели поставить задачу в понятной для машины форме, но когда речь заходит о проектировании внешнего вида и поведения, возникают сложности.
Веб дизайнеры же привыкли описывать, как должно выглядеть веб приложение, то есть ставить задачу, а не по пунктам описывать её решение, такой подход называется декларативным, он удобен, но к сожалению в традиционных приложениях до сих пор господствует именно императивный подход. Есть конечно дизайнеры форм, но они лишь позволяют в общих чертах обрисовать внешний вид приложения, но совершенно не способны описать его поведение. Для решения это проблемы в Qt Software был предложен новый проект Declarative User Interface и в рамках него новый язык разметки:

Встречаем QML


Это новый язык разметки, позволяющий описывать не только внешний вид, но и поведение ваших приложений. Он очень прост и обладает json образным синтаксисом, немного сближающим его html5, что думаю очень придется по душе веб-дизайнерам, да и программистам тоже. А в перспективе это наконец позволит полностью разделить внутреннюю логику работы приложения и его внешнее поведение, в результате чего будет наконец решена извечная проблема, когда программист занимается ещё и внешним видом приложения, потому, как дизайнерам слишком сложно было вникнуть в программирование.




Если вы хотите посмотреть на QML, то можете скачать специальную сборку QtCreator'а. В результате вы получите, помимо самого Созидателя, ещё и папку с примерами и скомпилированную программу-смотрелку.
Простейший Hello, World! Будет выглядеть так:


import Qt 4.6

Rectangle {
  width: 200
  height: 200
  color: "white"
  Text {
    text: "Hello World"
    anchors.centerIn: parent
  }
}

* This source code was highlighted with Source Code Highlighter.


Чуть посложнее пример, dial с видео:


import Qt 4.6
import "content"

Rectangle {
  color: "#545454"
  width: 300; height: 300

  // Dial with a slider to adjust it
  Dial { id: dial; anchors.centerIn: parent; value: slider.x *100 / (container.width - 34) }

  Rectangle {
    id: container
    anchors.bottom: parent.bottom; anchors.bottomMargin: 10
    anchors.left: parent.left; anchors.leftMargin: 20
    anchors.right: parent.right; anchors.rightMargin: 20; height: 16
    gradient: Gradient {
      GradientStop { position: 0.0; color: "gray" }
      GradientStop { position: 1.0; color: "white" }
    }
    radius: 8; opacity: 0.7; smooth: true
    Rectangle {
      id: slider
      x: 1; y: 1; width: 30; height: 14
      radius: 6; smooth: true
      gradient: Gradient {
        GradientStop { position: 0.0; color: "#424242" }
        GradientStop { position: 1.0; color: "black" }
      }
      MouseRegion {
        anchors.fill: parent
        drag.target: parent; drag.axis: "XAxis"; drag.minimumX: 2; drag.maximumX: container.width - 32
      }
    }
  }
}

* This source code was highlighted with Source Code Highlighter.


Впечатляет? Можно будет описывать таким образом различные состояния state машины, создавать сигналы/слоты, указывать с помощью какого эффекта должны переключаться различные состояния и ещё много чего.
Но пока это ещё только самые первые шаги, технология ещё не доросла до состояния готовности, пока это все даже не интегрировано в основную ветку разработки Qt, но самые смелые из вас уже сегодня могут погружаться в неё.
А чтобы потом в один прекрасный день не схватиться за голову с мыслью «господи, да мне же все теперь переписывать придется под этот QML», советую присматриваться уже сегодня к этой технологии и проектировать свои приложения так, чтобы она с легкостью встроилась в них. От себя советую побольше пользоваться dynamic property, так как их можно без лишних телодвижений сделать видимым из javascript и QML объектов.
Всю информацию о новой технологии можно найти здесь
Алексей Сидоров @Gorthauer87
карма
44,2
рейтинг 36,3
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (64)

  • +19
    Какая ужасная презентация, обрубок пальца оставил не совсем приятные впечатления, лучше бы обычной стрелочкой обошлись. Сказывается тренд Тач Скринов.
    • +2
      Вам бы только пальцы разглядывать ^_^. Специально вставил ещё одну презентацию без них
  • +14
    О, Боже, отрубленный палец!
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Простите, кого?
      • НЛО прилетело и опубликовало эту надпись здесь
        • –1
          designer в Qt был с незапамятных времен
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              Да и дизайнер в Qt в конечном счете генерирует вполне декларативный xml, но вот беда то в том, что логику работы им не опишешь, да и для каких то сложных случаев приходится по старинке всё делать прямо в C++ коде, здесь же все весьма просто упрощается за счет интеграции с javascript'ом
    • 0
      Не dfm, а XAML, только без XML.
  • –1
    не обижайтесь… но вообще не впечатляет.

    что собственно нового в том, что вы показали?
    Rectangle
    {
    width = 200
    }
    и кого это должно было восхитить? тут есть что-то чего ещё не было?

    из поста вообще не видно причём тут css и как это позволяет разделить работу дизайнера и программиста.

    не хочется преждевременно плеваться на чей-то труд… но пост просто убогий… честно…
    • +3
      Вам не угодишь, если начинаешь много кода вставлять, то никто статью в итоге не читает. В конце приведены ссылки на примеры, кому надо сами посмотрят.
      Но раз уж так не терпится, вставлю пример посложнее
  • –2
    Видио можно было и под кат засунуть.
  • +2
    Вы про WPF слышали? Презентации/примеры видели? Вполне себе такой декларативный подход, причем неплохо реализованный. Так что нового ничего нет, просто еще один вариант реализации.
    • +2
      Про WPF слышал, но насколько я знаю он базируется на xml'е, а QML на json, да и существование WPF не отменяет новизны подхода, пока он ещё только входит в обиход
      • +2
        а между xaml и json есть какие-то принципиально отличие?



        object { items: [subobject {name: «value»}] }

        как-то раз я даже писал конверт из xml в json и обратно. если придерживаться некоторых правил, то можно даже добиться взаимооднозначного соответствия.

        xaml в конечном счёте всё равно превращается в код, предполагаю, что QML тоже.

        а как у вас дела обстоят с разделением программист/дизайнер?
        к примеру в wpf широко используются DataTemplate. вы скармливаете контролу любой объект, и в зависимости от выбранного DataTemplate меняется его отображения.
        как я понял, у вас тоже есть нечто подобное… но в посте я этого не нашёл, как впрочем и на сайте.

        хотелось бы узнать поподробнее…
        • 0
          сорри… съелся xml код :) ну суть была в том, что они почти идентичны
        • +1
          Отличие в том, что json более человекопонятный сравните то, что я привел, с
          <Window x:Class="WpfApplication1.Window5"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="Тестовый пример" SizeToContent="WidthAndHeight">
          <StackPanel>
          <Button Click="Button_Click" Margin="5">Нажми меня</Button>
          <Button x:Name="btnTest" Margin="5" Padding="5">Тестовая кнопка</Button>
          <Button Margin="5" Padding="5">
          <StackPanel Orientation="Horizontal">
          <TextBlock VerticalAlignment="Center">Кнопка</TextBlock>
          <Image Source="Bitmap1.bmp" Margin="5" />
          <TextBlock VerticalAlignment="Bottom">с картинкой</TextBlock>
          </StackPanel>
          </Button>
          </StackPanel>
          </Window>


          * This source code was highlighted with Source Code Highlighter.

          json, банально, читать проще. А здесь немного другая идеология, чтобы её понять, нужно немножко Qt знать. Вы про сигналы/слоты слышали, а про state machine? Далее, QML тесно интегрирован с javascriptом. Можно вот такие штуки делать
          script {
          function photoClicked() {
          imageDetails.photoTitle = title;
          imageDetails.photoTags = tags;
          imageDetails.photoWidth = photoWidth;
          imageDetails.photoHeight = photoHeight;
          imageDetails.photoType = photoType;
          imageDetails.photoAuthor = photoAuthor;
          imageDetails.photoDate = photoDate;
          imageDetails.photoUrl = url;
          imageDetails.rating = 0;
          scaleMe.state = "Details";
          }
          }

          В принципе сделать также, как в wpf, не составит труда.
          Вообще пока ещё нету полной документации по технологии, релиз видимо лишь в следующем году состоится, да и я всё же не представитель Qt Software.
          • 0
            лично мне xml читать как-то сподручнее чем json…
            хотя… если вам угодно:

            new Grid()
            {
                Width = 100,
                Height = 200,
                Children =
                {
                    new TextBox() { Text = "some text" },
                    new Button() { Content = "Button1" }
                }
            };

            это тот же wpf, только не на xaml, а на C#
            можно и так и так писать…

            а как у вас с биндингом (или как он у вас называется)?
            • 0
              Ну вопрос привычке, я привык к сишному синтаксису, а json больше на него похож. Кто вырос на html'е наверное имеет другое мнение.
              В смысле биндингом? Я в .NET'е плохо ориентируюсь. Qt это фреймворк, написанный на C++, но с использованием метаданных, которые в том числе позволяют реализовывать лёгкую привязку к javscriptу, грубо говоря можно обычные Qtшные обьекты (унаследованные от QObject) делать доступными для скриптов. Здесь тот же самый механизм применён.
              Вообще вам помоему сюда
              • 0
                упростим вопрос:
                у вас есть какой-то input. как введённое значение присвоить какому-то свойству объекта?
                • 0
                  Конечно есть, советую взглянуть на демки, например, на web browser
                  лежит в demos/declarative/webbrowser
                  • 0
                    Чтобы не ставить себе весь пакет, может быть вкратце изложите суть? А то терзают смутные сомнения насчет привязок — например, как они задаются в этой json-разметке и как работают.
                    • 0
                      А, сорри, я был невнимателен:
                      value: slider.x *100 / (container.width - 34)

                      Однако, есть подозрение, что работать это будет только для визуальных элементов, которые должны иметь имя. Привязаться таким образом к полям произвольного объекта нельзя. Верно?
                    • 0
                      pastebin.ca/1672687
                      Вот тут пример. Из кода всё очевидно
                      MouseRegion {
                      anchors.fill: confirmIcon
                      onClicked: { confirm() }
                      }

                      TextInput {
                      id: textEdit
                      text: fieldText.text
                      focus: false
                      anchors.left: parent.left
                      anchors.leftMargin: 0
                      anchors.right: parent.right
                      anchors.rightMargin: 0
                      anchors.verticalCenter: parent.verticalCenter
                      color: "black"
                      font.bold: true
                      readOnly: true
                      onAccepted: confirm()
                      Keys.onEscapePressed: reset()
                      }

                      Когда мы кликаем в определенное место на форме, которое помечено якорем (в данном случае якорь указывает на иконку confirm), или просто генерируем событие Accepted, вызывается javascript функция confirm(), которая считывает данные из input'а, присваивает их объекту, а потом отсылает сигнал confirmed, который ловится браузером
                      • 0
                        Не, это не интересно — это обычная обработка событий.

                        Биндинг — это когда при изменении свойства какого-либо объекта автоматически меняются зависящие от него свойства других объектов. Например, когда меняется значение в текстовом поле, то автоматически меняется и значение в соответствующей записи в таблице данных, и наоборот.
                        • +1
                          А что мешает это через сигналы/слоты сделать? (кстати в WPF есть аналоги для сигналов/слотов или их более мощного варианта — state машины?)
                          Вообще это ещё далеко не релиз, а статья больше ориентирована на Qt разрабов, чтобы они как-то обратили внимание на то, что их ждёт в будущем и начали хоть как-то готовить свои графические приложения к использованию этой технологии.
                          • 0
                            Мешает то, что это нужно делать. А потом — поддерживать. И при изменении в UI или в логике переделывать обработчики событий.

                            WPF — это Presentation, стейт-машинам в нем делать нечего. Для них есть Workflow Foundation.
                            А сигналы/слоты — это обычные события и их обработчики в терминологии .NET. Они есть независимо от WPF — хоть в WinForms, хоть вообще без всякого GUI.
                          • 0
                            State Machine — есть.
                            DataBinding там отличный (как вам, например Text="{Binding Company.Boss.Name, Mode=TwoWay}). При изменении текста — изменяется свойство Name, в свойстве Boss в свойстве Company объекта из текущего контекста.
                            XML выглядит понятнее.
                            Всякая декларативная логика, а у же тем более привязка к событиям элементов управления на форме — элементарно.
                          • 0
                            есть Visual State Manager, позволяющий определить состояния объектов и способы переходов между ними
                        • +1
                          дык это все реализуется спокойно механизмом сигнал-слотов.
                          при изменении например значения в текстовом поле генерируется сигнал changed() (точно названия не помню но идея думаю ясна...). его можно например связать со слотом update() у таблицы и таким образом при изменении данных в поле ввода будут меняться данные в таблице…
                          • 0
                            не успел((
                          • 0
                            А changed() у таблицы — со слотом update() у поля? А не зациклит?
                            • 0
                              не зациклит.
                              • 0
                                Ок, а как выглядит слот update() у таблицы? Мы сами его пишем, или стандартный?
                                Если стандартный, то он учитывает, что значение поля может отображаться в нескольких визуальных полях и что нужно обновить остальные, кроме пославшего changed?
                                И раз это слот таблицы, то он что, опрашивает изменения для всех записей? Не приведет ли это к потере производительности?

                                И как в этом сценарии добавляется, например, валидация ввода? Или преобразование форматов/типов?

                                Не холивара ради, мне просто любопытно :)
                                • +1
                                  Берем и пишем, что нам нужно.
                                  И никого он не опрашивает, он же слот, он не должен этим заниматься. Он лишь ждёт, когда на него придет сигнал, сигнал может быть соединен с любым количеством слотов или других сигналов, тогда сигналы будут по цепочке передаваться.
                                  Короче советую победить лень и скачать таки тот файл, на который я ссылку дал и изучить демки
                                  • 0
                                    Ок, на слот update() таблицы приходит сигнал. Это означает, что таблица поменялась. Соответственно, ей нужно со всех связанных визуальных элементов собрать данные. Даже если она знает, от какого визуального элемента пришел сигнал, то все равно нужно реализовывать логику переноса значения из этого элемента в соответствующее поле той записи, которая в настоящий момент ассоциирована с текстовым полем.

                                    Пример посмотрел. Из чего-то, напоминающего биндинг, там только
                                    color: fieldText.state == "editing" ? "#505050" : "#AAAAAA"
                                    , остальное же — обычный код обработки событий, причем, как я понимаю, соответствие там одностороннее, в обратную сторону такая штука работать не будет.
                                    • 0
                                      как я понял из выше написанного — простого советского биндинга там нет. но они по этому поводу не особо расстраиваются и просто им не используются.

                                      хотя… имея механизм уведомлений, биндинг всегда можно написать самому.
    • +1
      скорее XAML, а не WPF, ибо для WPF возможен и «императивный» подход — описание кодом, а не разметкой. да, я зануда)
      по сути согласен, что «всё это уже было», да и принципиальной разницы между xml и json нет
      • +1
        Есть. На xml писать лень, а на json — приятно.
        • 0
          кому? вам? это слишком субъективно
          • 0
            забыл дописать что это имхо.
            Но думаю что все-таки людей, которым json нравится лучше чем xml — больше )
  • 0
    Опять этот страшный палец
  • +10
  • +9
    это JavaFX
  • +5
    Ладно, давайте тогда сойдёмся во мнении, что в C++, по-моему такого решения ещё не было. Да и вообще, в очередной раз понимаю, что Тролли (не Хабравские, а из бывшего Trolltech) — молодцы, стараются всеми силами сделать C++ ещё более могучим и самое главное, близким и понятным для разработчиков.

    Спасибо.
    • 0
      Такое было с незапамятно-бородатых времен. Борланд C++ билдер, и тамошнее устройство оконных форм.
      Концепция была архиправильная, и порожает, почему в 2009 году ее никто еще не слизал 1:1 а все изобретают свои велосипеды неюзабельные.
  • +3
    А я считаю, что не стоит путать слова новый и первый.
  • 0
    Это не новый подход. Авторы явно вдохновились конфигами Hybrid для D: hybrid.team0xf.com/wiki/Main/ConfigFiles
    • 0
      Хабрачеловека, поставившего минус прошу:
      1. Перечитать хабраэтикет;
      2. Показать, где принципиальная разница или иным образом, объяснить, где я не прав.
      • 0
        Также прошу перечитать хабраэтикет ипрокомментировать минусовавшего карму.

        Чувствую себя полным идиотом, в упор не видящим своей ошибки.
    • 0
      Тоже вспомнил про Hybrid.
  • –3
    какой-то страшный JSON
  • 0
    Как понимаю, модуль QtGui в новой версии Qt увеличится в объеме раза в два. Мелкие утилитки и Qt станут совсем несовместимыми понятиями.
    • 0
      Не думаю, что парсер json сильно утяжелил библиотеку. Что касается размера, то мелкие утилиты и ранее были не особо совместимы с Qt — вернее, они априори не были мелкими :)
      • +1
        sauron@northrend ~/Develop/qutim/sdk03 $ cat 3rdparty/k8json/k8json.cpp | wc -l
        788

        Это разве много? Парсит в QVariant. И что разве размер QtGui как то влияет на размер исполняемых файлов? Qt как бы оптимизируют под embedded устройства поэтому с производительностью там всё хорошо
        • –3
          Размер QtGui влияет на размер дистрибутива.
          • +3
            В Линуксе её вообще лишь один раз придется поставить, пользователи Windows'а обычно редко жалуются, они и без этого привыкли к весьма пухленьким дистрам, это может быть критично лишь на embedded устройствах, но в Qt есть опции сборки, позволяющие для таких устройств выкидывать ненужные части.
            Сейчас дистрибутивы куда больше разъедаются на всякой графической и мультимедийной информации.
    • +2
      Мелкие утилитки несовместимы с графическими интерфейсами.

      А для графических морд к мелким утилиткам пока ничего лучше Tcl/Tk не придумали.
  • 0
    Не дайте Астронавтам Архитектуры вас запугать
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Вспомнился Delphi 1.0 со своими .DFM файлами. Между прочим 95го года среда разработки. И не прошло 14-и лет как в QT добрались до декларативного описания форм…
    • 0
      Декларативное описание форм в Qt идёт, если не с тех лет, то ооочень давно, с 90ых точно. Посмотрите ui файлы. Но в ui файлах почти никак не описывается логика, только соединение слотов и сигналов и подобные мелочи, а тут же куда большие возможности открываются
      • 0
        Ума не приложу зачем валить все в одну кучу. Есть описание формы, есть код. Когда в форме прописаны еще условия и состояния это получается какойто php, где в одну кучу свалено. Если уж начали доводите до конца — берите пример с борландовых .dfm. Там исключительно описание контролов и ресурсов. Все изменения состояний, код и прочие — в отдельном файле.

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