[Qt, Разработка под Linux, Разработка под Windows] Портирование приложений с QWidget на QML под Desktop
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабровчане!
Последнее время часто встречаю проекты для desktop, которые необходимо портировать с QWidget на QML. Кто-то хочет написать с нуля, кто-то перенести старые наработки. В любом из сценариев это популяризация QML, чему я очень рад. Я решил тоже побыть полезным и поделиться своими наработками и ситуациями из личной практики. Возможно, некоторые из них покажутся вам простыми и понятными, однако если я что-то упустил, буду рад почитать об этом в комментариях.
Кратко о QML и QWidget
QML — это декларативный язык программирования. Он позволяет разработчикам и дизайнерам создавать удобные, плавно анимированные и визуально привлекательные приложения. QML предлагает читаемый декларативный JSON-подобный синтаксис с поддержкой императивных выражений JavaScript в сочетании с динамическими привязками свойств.
QWidget — это предшествующая QML технология для создания пользовательского интерфейса, основанная на использовании заранее созданных desktop-style компонентов и предоставляющая API для взаимодействия с ними.
Пользовательский опыт
Около года назад я нашел прекрасный инструмент для работы с гитом gitAhead и в целом я доволен большей частью функционала и он мне часто помогает. Но на этом примере прекрасно видно, что виджетам не хватает гибкости и функционала. Из-за этого невозможно покрыть больше пользовательских сценариев и сделать более дружелюбный интерфейс. В итоге вместо отличного дерева коммитов и дифов, мы имеем огромное количество ограничений.
Стандартное окно(кликабельно)
SPL
Дизайн приложения и его влияние на портирование
Классически Qt нам советует придерживаться паттернов MVC\MVP, где всё взаимодействие с UI вынесено в отдельные сущности, что позволяет нам изменять их, не затрагивая остальные части приложений и бизнес логику. Абстрагирование элементов и возможность встраивать QML-компонент в стандартный QWidget позволяет гибко подойти к плану дальнейшей работы. Если вы сейчас на этом пункте, то я бы хотел вам посоветовать продумать требования и функциональность будущего приложения, нарисовать его макет, посоветоваться с дизайнерами, опросить пользователей или заказчика. В целом решить как вы будете жить ближайшее время, и какие вопросы будете решать. И выбрать один из двух путей, предложенных ниже.
План А «С чистого листа»
Мы убираем весь старый UI, виджеты, зависимости, legacy код и оставляем только требования и функциональность, которые нам необходимо будет восстановить. Хорошая возможность улучшить архитектуру, подготовить почву для новых изменений. При подготовке необходимо учитывать следующие вещи, которые изменяются при переходе от одной библиотеке к другой и лучше продумать их заранее:
- Библиотека элементов. Создайте свою начальную базу элементов, где пропишите базовые настройки для элементов, их вид и состояния по умолчанию. Если есть возможность, оберните их тестами. В одной из конфигураций проекта сделайте их копируемыми в папку проекта, а не компилируемыми в бинарный*.qrc, это позволит вам править эти сборки в runtime без дополнительных компиляций и подключать qmllive и его аналоги.
- Отсутствие QAction. В приложениях на QWidget, частым гостем является и QAction, расширяющий возможности перехвата действий пользователя как по нажатию кнопки на экране, так и перехватом горячих клавиш. К сожалению в QML QAction переехал в несколько ином виде и позволяет только из QML обертки перехватывать заранее определенные горячие клавиши, что накладывает ограничения на использование его внутри C++ или создавать динамически. Здесь вы можете написать свою реализацию, использовать event-filter от qobject или использовать сторонние проекты, такие как QHotkey.
В остальном здесь всё типично для приложения на C++ и QML.
План Б «У нас типо agile»
Так как для Agile одной из главной ценностью является работающий продукт, то мы должны делать переезд поэтапно, без регресса функционала. Для этого мы делим весь UI на логические сегменты с минимальным количеством взаимозависимостей и реализуем их отдельно. На примере gitAhead можно рассмотреть следующий вариант(выделил зеленым):
Разделение UI на сегменты(кликабельно)
SPL
Для каждой из областей мы создадим родительский виджет, в который и положим корневой QML элемент. Это можно сделать двумя способами.
Создать QQuickWidget
QQuickWidget *view = new QQuickWidget;
view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
view->show();
Или вызывать метод QWidget::createWindowContainer(...)
QQuickView *view = new QQuickView();
...
QWidget *container = QWidget::createWindowContainer(view);
container->setMinimumSize(...);
container->setMaximumSize(...);
...
widgetLayout->addWidget(container);
Разница между предложенными способами в том что QQuickWidget является более гибкой альтернативой чем QWidget::createWindowContainer(...), ведя себя больше как обычный QWidget. При этом большая функциональность достигается из-за незначительных потерь в производительности.
Дальнейшая работа производится как с обычным QQuickView, за исключением следующих особенностей:
- Ограниченный контекст. У каждого родительского QWidget будет свой QML-контекст, что в свое очередь накладывает ограничения на область видимости. Свои property, функции, объекты и т.д. Каждый widget по сути становится независимой «песочницей»
- Ограничение по размеру виджета. В ходе создания виджета, можно создать правило чтобы размеры виджета следовали за размерами контента внутри и по сути это правильно. Но это распространяется только на корневые элементы внутри этого QML, а все временные объекты с размерами превышающими виджет, будут обрезаться границами. Хорошим примером тут может служить всплывающая подсказка для кнопок, если кнопки маленькие, при это есть большое описание, то часть подсказки скроется за границей виджета. Если размеры виджета-контейнера поставлены не по размеру контента, то это так же может привести к проблемам при масштабировании интерфейса. Частично эта проблема решается элементами из lab.
Пример выхода за границы и неправильной верстки
SPL
- 3D графика. Здесь всё усложнено и полно ограничений, рекомендуется использовать QQuickWidget и есть не маленькая вероятность что именно ваш сценарий либо потребует «костылей», либо больших трудовложений, поэтому ознакомьтесь с ограничениями заранее, либо сразу реализуйте под использование в QML
Стоит напомнить что приведенные выше ограничения распространяются только на тот период, пока вы переносите свою элементную базу. Описанные же в плане А ограничения распространяются на всё приложение. Последним элементом будет являться базовое окно приложения, где необходимо будет всё расположить в соответствии с дизайном, работой фокуса и др. требованиями. Останется удалить последние зависимости приложения от QWidget библиотеки, убрать ее из поставки и всё, работа закончена. Вы молодцы!
Итоги
Над gitAhead мне предстоит еще много работы, и не только по UI, но приблизительно как это происходит я описал. Если вам понравилась идея и вам хочется поучаствовать, то буду рад сотрудничеству. Мой репозиторий будет тут.
===========
Источник:
habr.com
===========
Похожие новости:
- [История IT, Разработка под Linux, Терминология IT] Разработчики ядра Linux планируют заменить часть терминов в коде на нейтральные названия
- [Инженерные системы, Интернет вещей, Производство и разработка электроники, Промышленное программирование] Edge платформа промышленного интернета вещей I-IoT
- Выпуск рабочего стола MaXX 2.1, адаптации IRIX Interactive Desktop для Linux
- [IT-инфраструктура, Open source, Разработка под Linux, Учебный процесс в IT] Наши уникальные бесплатные мастер-курсы Kubernetes, CLI tool для разработчиков Odo, Java в контейнерах и много книг
- [Microsoft Edge, Дизайн, Интерфейсы, Разработка под Windows, Софт] В Windows 10 Developer Preview 20161 показали обновления меню «Пуск» и режима миниатюр в Edge
- [*nix, C, Open source, Звук, Разработка под Linux] Изучаем VoIP-движок Mediastreamer2. Часть 13, заключительная
- [IT-инфраструктура, Open source, Виртуализация, Разработка под Linux, Сетевые технологии] Интеграция Open vSwitch с Р-виртуализацией
- [Интернет вещей, Программирование микроконтроллеров, Разработка для интернета вещей, Разработка систем связи] MQTTv5.0: Обзор новых функций
- [Законодательство в IT, Разработка под Windows] США запретили продавать Windows и iPhone российским военным и полиции
- [Open source, Разработка под MacOS, Разработка под Windows, DIY или Сделай сам] Говорим и показываем: как мы создали сервис синхронного просмотра видео ITSkino на основе VLC
Теги для поиска: #_qt, #_razrabotka_pod_linux (Разработка под Linux), #_razrabotka_pod_windows (Разработка под Windows), #_qt, #_qml, #_desktop, #_qt, #_razrabotka_pod_linux (
Разработка под Linux
), #_razrabotka_pod_windows (
Разработка под Windows
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:18
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабровчане! Последнее время часто встречаю проекты для desktop, которые необходимо портировать с QWidget на QML. Кто-то хочет написать с нуля, кто-то перенести старые наработки. В любом из сценариев это популяризация QML, чему я очень рад. Я решил тоже побыть полезным и поделиться своими наработками и ситуациями из личной практики. Возможно, некоторые из них покажутся вам простыми и понятными, однако если я что-то упустил, буду рад почитать об этом в комментариях. Кратко о QML и QWidget QML — это декларативный язык программирования. Он позволяет разработчикам и дизайнерам создавать удобные, плавно анимированные и визуально привлекательные приложения. QML предлагает читаемый декларативный JSON-подобный синтаксис с поддержкой императивных выражений JavaScript в сочетании с динамическими привязками свойств. QWidget — это предшествующая QML технология для создания пользовательского интерфейса, основанная на использовании заранее созданных desktop-style компонентов и предоставляющая API для взаимодействия с ними. Пользовательский опыт Около года назад я нашел прекрасный инструмент для работы с гитом gitAhead и в целом я доволен большей частью функционала и он мне часто помогает. Но на этом примере прекрасно видно, что виджетам не хватает гибкости и функционала. Из-за этого невозможно покрыть больше пользовательских сценариев и сделать более дружелюбный интерфейс. В итоге вместо отличного дерева коммитов и дифов, мы имеем огромное количество ограничений. Стандартное окно(кликабельно)SPLДизайн приложения и его влияние на портирование Классически Qt нам советует придерживаться паттернов MVC\MVP, где всё взаимодействие с UI вынесено в отдельные сущности, что позволяет нам изменять их, не затрагивая остальные части приложений и бизнес логику. Абстрагирование элементов и возможность встраивать QML-компонент в стандартный QWidget позволяет гибко подойти к плану дальнейшей работы. Если вы сейчас на этом пункте, то я бы хотел вам посоветовать продумать требования и функциональность будущего приложения, нарисовать его макет, посоветоваться с дизайнерами, опросить пользователей или заказчика. В целом решить как вы будете жить ближайшее время, и какие вопросы будете решать. И выбрать один из двух путей, предложенных ниже. План А «С чистого листа» Мы убираем весь старый UI, виджеты, зависимости, legacy код и оставляем только требования и функциональность, которые нам необходимо будет восстановить. Хорошая возможность улучшить архитектуру, подготовить почву для новых изменений. При подготовке необходимо учитывать следующие вещи, которые изменяются при переходе от одной библиотеке к другой и лучше продумать их заранее:
В остальном здесь всё типично для приложения на C++ и QML. План Б «У нас типо agile» Так как для Agile одной из главной ценностью является работающий продукт, то мы должны делать переезд поэтапно, без регресса функционала. Для этого мы делим весь UI на логические сегменты с минимальным количеством взаимозависимостей и реализуем их отдельно. На примере gitAhead можно рассмотреть следующий вариант(выделил зеленым): Разделение UI на сегменты(кликабельно)SPLДля каждой из областей мы создадим родительский виджет, в который и положим корневой QML элемент. Это можно сделать двумя способами. Создать QQuickWidget QQuickWidget *view = new QQuickWidget;
view->setSource(QUrl::fromLocalFile("myqmlfile.qml")); view->show(); Или вызывать метод QWidget::createWindowContainer(...) QQuickView *view = new QQuickView();
... QWidget *container = QWidget::createWindowContainer(view); container->setMinimumSize(...); container->setMaximumSize(...); ... widgetLayout->addWidget(container); Разница между предложенными способами в том что QQuickWidget является более гибкой альтернативой чем QWidget::createWindowContainer(...), ведя себя больше как обычный QWidget. При этом большая функциональность достигается из-за незначительных потерь в производительности. Дальнейшая работа производится как с обычным QQuickView, за исключением следующих особенностей:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 00:18
Часовой пояс: UTC + 5