#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
orQStandardItem
не помечена как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