DroidScript
DroidScript
учимся и разрабатываем

QML WebSockets: одновременный просмотр работы кода на нескольких устройствах

25.11.2017

Если среда прототипирования, разработки и выполнения приложения различаются, то его интерфейс, взаимодействие с ним и функциональность также будут отличаться, что в конечном итоге потребует его адаптацию. Можно ли всё указанное выше производить в одной среде? При одноплатформенной настольной разработке это возможно, а при кроссплатформенной - нет. К тому же, каждая среда имеет свои преимущества:

  • Настольная оконная среда - привычная, удобная и эффективная работа на мощном компьютере и большом мониторе в функциональных IDE, быстрая компиляция и запуск
  • Браузерная среда - легкие в работе инструменты, запуск без компиляции кода и установки приложения
  • Мобильная среда - наглядность

С учётом этих моментов обозначим задачу конкретнее: редактировать QML-код в Qt Creator под Windows и просматривать его работу в Windows и на устройстве Android в реальном времени без перекомпиляции.

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

Просмотр работы кода будет осуществляться после его сохранения в файле целевой директории. Для этого необходимо создать модуль детектора, постоянно сканирующего целевую директорию на предмет изменения в ней количества файлов или их содержимого. При обнаружении изменений, что можно отследить по времени изменения файлов, детектор направляет содержимое целевого (или изменённого файла) серверу, который пересылает его всем подключенным к нему клиентам. Клиенты получают содержимое файла в виде строки, интерпретируют её в QML-код и произодят его вывод в свою рабочую область.

В QML есть поддержка websockets и таймера, но нет поддержки работы с файловой системой, поэтому модуль детектора пишется на Qt C++.

Интерфейс всех модулей будет выполнен на QML, для чего нужно создать три проекта Qt Quick Controls 2: детектор, сервер, клиент. В качестве основной среды - среды разработки - выберем Windows. В этом случае функции модулей будут следующими.

  1. Детектор - windows-приложение, сканирующее целевую директорию файловой системы Windows на предмет её изменения. Для связи с сервером в детектор необходимо включить сокет-клиент на QML.
  2. Сервер - универсальный модуль, который может быть запущен на любом устройстве. Содержит в себе список адресов подключенных к нему клиентов.
  3. Клиент - универсальный модуль, который может быть запущен на любом устройстве. В его задачу входит отображение на экране QML-кода.

Порядок запуска модулей следующий: сначала запускается сервер, затем клиенты - детектор и два клиента - на Windows и Android.

В целях уменьшения количества приложений и запусков, детектор можно совмеcтить с сервером и клиентом. В этом случае будет два приложения - универсальное приложение на Windows и клиент на Android. Но это уменьшит гибкость системы.

Код проектов можно загрузить здесь, а мы рассмотрим некоторые его части.

main.cpp (детектор)

В детекторе функциональность QML дополнена Qt C++. Создание связи между ними производится в следующей строке:

engine.rootContext()->setContextProperty("fl", &fl);

Здесь QML-свойству c именем fl присваивается значение ссылки на объект Qt-класса CheckFileList.

checkfilelist.cpp (детектор)

Проверка изменений файлов производится по таймеру, что является универсальным, но неэффективным решением. Для рашения этой задачи предназначен класс QFileSystemWatcher, объекты которого формируют сигналы при обнаружении изменений в файловой системе.

При обнаружении изменений серверу передаётся содержимое одного и того же файла Test.qml. Метод Qt.createQmlObject возвращается немедленно и может не работать, если строка QML загружает внешние файлы QML, которые еще не были загружены. Если так и происходит, то рекомендуется использовать метод Qt.createComponent.

При использовании Qt.createComponent и блока Loader содержимое кэшируется и при следующем их вызове будут загружены данные не из указанного в их параметрах файла, а из кэша. Для очиски кэша используется методы clearComponentCache() или trimComponentCache() объекта QQmlEngine.

main.qml (детектор)

После создания свойства fl и присваивании ему ссылки на Qt-класс в файле main.cpp можно из QML обращаться к методам этого класса (в блоке Timer) и получать от него сигналы (блок Connections).

websocketserver.qml (сервер)

websocketclient.qml (клиент)

Работу сокетов практичнее отлаживать на локальном хосте, после чего можно будет перейти к проверке её работы в сети. Для этого нужно изменить значение свойства host сервера на ip-адрес компьютера, на котором он запускается (типа 192.168.x.x), указать этот адрес в свойстве url всех клиентов - Windows и Android, и скомпилировать последний для Android. При этом соединяемые устройства должны находится в одной cети (подключены к одному роутеру, проще говоря).

Если что-то не работает, то для начала проверяем доступность компьютеров в сети пингом их ip и настраиваем брандмауэр. Если всё в порядке, то можно попробовать наладить тестовую связь между веб-сокет сервером на Node.js и сокет-клиентом на JavaScript. Когда эта связка заработает, то к серверу на Node.js можно подключить клиента на QML для проверки работы последнего или к QML-серверу клиента на JavaScript.

© 2016-2024 
actech