Доступ к Qt API из JavaScript с помощью QJSEngine

#c #qt #qjsengine

#c #qt #qjsengine

Вопрос:

Я использую a QJSEngine , чтобы сделать приложение скриптовым. Я бы хотел, чтобы сторона JavaScript могла изменять пользовательский интерфейс. Моя главная проблема сейчас — доступ к Qt API из JavaScript.

Для создания виджетов я добавил createWidget() оболочку, которая использует QUILoader :

 // JavaScript
var w = helpers.createWidget("QPushButton");

// C  
QJSValue helpers::createWidget(QString type)
{
    QUILoader ld;
    return engine.newQObject(ld.createWidget(type));
}
  

Я также зарегистрировал все перечисления из qt_getQtMetaObject() , которые, похоже, заботятся обо всех перечислениях на уровне пространства qnamespace.h имен. Однако не похоже, что это часть общедоступного API.

Я действительно должен делать это вручную или я что-то упускаю? Разве нет registerAllTheThings() функции, которая создает глобальный Qt объект, через который доступен Qt API?

Если нет, то у меня проблема. Я могу создать QWidget s с помощью a QUILoader , но я не смог найти способ создания других объектов, таких как a QStandardItemModel . Я думал, что все классы Qt уже будут зарегистрированы qRegisterMetaType() , но это не так: QMetaType::type("QStandardItemModel") сбой при возврате UnknownType . Опять же, я пропускаю какой-то вызов функции инициализации, который регистрирует все?

Комментарии:

1. Хорошо, ни одна из функций-членов в QStandardItemModel or QStandardItem не помечена как Q_INVOKABLE , поэтому я даже не могу их вызвать. Возможно, я просто переоценил возможности Qt по написанию сценариев.

2. Если вам нужно скриптовое приложение, используйте QML вместо QtWidgets. Затем вы можете использовать JS изначально со всем вашим API. Вам может сойти с рук использование очень небольшого количества кода на C в ядре. Делать это с помощью QtWidgets крайне навязчиво. Сделать это в QML очень просто. QML «компилируется» на ходу, поэтому с помощью генерации кода вы можете создавать совершенно новые типы во время выполнения.

3. @ddriver На самом деле это то, над чем я работал последние 4 часа, но это только для расширений. Основное приложение написано на C . В настоящее время я пытаюсь загрузить файлы QML во время выполнения, но я пока не уверен, как они будут взаимодействовать с QtWidgets.

4. Вам нужно будет выполнить оооооочень много интерфейсов…

5. Ну, эти классы C Qt задолго предшествуют QML, поэтому неудивительно, что они не предназначены для использования из QML. Кроме того, я уже сказал, что это довольно плохая идея. Если ваше приложение не слишком большое, его будет проще перенести на QML.

Ответ №1:

Я бы рекомендовал использовать a QQmlEngine вместо QJSEngine .

Is является производным от QJSEngine, поэтому он может делать то же самое в том же модуле, поэтому никаких дополнительных зависимостей.

Он обеспечивает простой способ регистрации типов для создания экземпляров в QML, имеет механизм загрузки плагинов (импорт) и т.д.

Я представил это в рамках своего выступления на Qt World Summit 2015: https://www.youtube.com/watch?v=7LsKoVrb8C8

Комментарии:

1. Поиграв с этим несколько часов, я понял, что QML — это гибрид, который требует C для определенных задач, таких как модель для a TreeView . Кажется, это не очень подходит для написания расширений. Я прав?

2. В основном все типы, которые не являются частью языка JavaScript, в какой-то момент поддерживаются кодом C . Даже типы самого JavaScript могут напрямую преобразовываться в типы C , но это скрыто внутри движка. При использовании QML для пользовательских интерфейсов, например, с помощью QtQuick, каскадов BB10 или декларативных виджетов, модели часто реализуются непосредственно на C . Но можно также создавать базовые типы, которые затем могут быть расширены и / или заполнены на стороне скрипта, например, QtQml. Модели ListModel

3. @KevinKrammer Я знаю, что это было давно, но можно ли опубликовать код?

4. @bibi Слайды и демонстрационный код доступны с kdab.com/development-resources/kdab-qt-world-summit-2015 Просто прокрутите вниз до записи моего выступления У меня также было последующее выступление на Qt World Summit 2019 kdab.com/kdab-qt-world-summit-2019/#qml-scripting