QT QML Items как в C ++, так и в QML

Моя цель - описать элемент qml в файле qml, а затем использовать соответствующий класс C ++ для добавления к визуальному представлению этого элемента.

Я знаю, что можно описать элемент qml и использовать его в файле qml и общаться с ним из C ++ через сигнал / слоты.

Я также знаю, что можно описать элемент qml на C ++ с помощью QQuickPaintedItem и использовать его в файле qml (делая его доступным через механизм регистрации). Есть ли другие способы?

Итак, актуальный вопрос: можно ли объединить и то, и другое в одном предмете? Итак, я хочу, чтобы элемент qml и класс C ++ рисовали одну и ту же область, например. У меня есть конкретный код OpenGL на С ++ и обычный прямоугольный фрейм с MouseArea, определенным в qml.


person PsiX    schedule 13.07.2016    source источник
comment
Создайте свой собственный элемент на C ++. C ++ - это язык компиляции, qml интерпретируется (во время выполнения), поэтому невозможно использовать определения qml во время компиляции.   -  person Dmitry Sazonov    schedule 13.07.2016
comment
С QQuickPaintedItem я могу использовать объекты C ++ в qml. С помощью object- ›findChild‹ QObject * ›(myobject) я могу использовать объекты qml в C ++. Вопрос в том, существует ли объект, который похож на QQuickPaintedItem, но также может иметь визуальное представление qml. Шаблоны qt.labs. кажутся интересными.   -  person PsiX    schedule 13.07.2016
comment
Вы можете объединить C ++ и QML в один элемент, поместив элемент, производный от QQuickPaintedItem, над элементом QML. Вы можете сделать это, настроив свойство z ​​или просто упорядочив элементы соответствующим образом в одном файле QML. Поскольку QQuickPaintedItem имеет прозрачный фон, вы увидите вывод своего рисунка как из C ++, так и из QML.   -  person Andrej Repiský    schedule 13.07.2016
comment
Просто добавьте к нему что-нибудь в QML: MyPaintedItem { Rectangle{} } и сохраните в MyPaintedItemWithRectangle.qml. Затем используйте тип MyPaintedItemWithRectangle.   -  person Velkan    schedule 13.07.2016
comment
@Velkan Это не помогает с рендерингом в коде.   -  person PsiX    schedule 13.07.2016
comment
@PsiX, я использую это при выводе из QQuickItem, и рендеринг работает.   -  person Velkan    schedule 13.07.2016


Ответы (1)


После подсказки Андрея я решил реализовать свою цель - иметь как представление qml, так и класс рендеринга C ++, создав класс-оболочку, производный от QQuickPaintedItem, и тем самым переопределив метод рисования. С его помощью я могу визуализировать элемент в коде. Этот элемент используется в моем основном файле qml.

Это класс-оболочка, потому что он загружает файл qml, который я хочу показать, через QQmlComponent, который создает QuickItem, который я тоже хочу показать. Я делаю это, устанавливая родительский элемент загруженного / созданного элемента в свой класс-оболочку. Итак, в моем классе QuickPaintedItem (лучше всего в classbegin, когда движок уже инициализирован):

QQmlComponent component(engine,QUrl("qrc:/myqml.qml")); QObject* object = component.create(); QQuickItem* quickItem = qobject_cast<QQuickItem*>(object); quickItem->setParentItem(this);

Затем визуализируется myqml.qml и мой метод рисования. И у меня есть центральное место, где я могу использовать и то, и другое.

После комментариев Велкана еще один способ - поместить загрузку компонента в Загрузчик qml item:

Wrapper { Loader{ onQmlChanged: source = newQml } }

где onQmlChanged будет слотом, который потребляет сигнал:

signal onQmlChanged(string newQml);

Я не могу сказать, какой способ лучше с точки зрения производительности. Определение структуры в qml кажется проще и чище. Отличие от версии кода заключается в том, что он загружает элемент во время создания Wrapper, то есть во время создания main.qml и до его отображения.

person PsiX    schedule 13.07.2016
comment
Чем он отличается от Wrapper { MyQml{} }? Wrapper - это QQuickPaintedItem, родительский элемент для MyQml из файла myqml.qml. - person Velkan; 13.07.2016
comment
Я могу загрузить qml во время выполнения. Это требование. - person PsiX; 14.07.2016
comment
Во время выполнения: Wrapper { Loader{source:...} }. - person Velkan; 14.07.2016
comment
Источник, имя файла qml-файла также читается во время выполнения. - person PsiX; 14.07.2016
comment
Все во время выполнения и динамически: Wrapper { Loader{ onSomething: source = "myqml.qml" } } - person Velkan; 14.07.2016
comment
Хм, так что, если я получу файл qml из удаленного источника (например, загрузил его в свое приложение), я могу установить свойство источника объекта Loader в моем Wrapper? Примерно так: (qobject_cast ‹QQuickItem *› (wrapper- ›findChild‹ QObject * ›(loaderId)) -› setProperty (source, myqml.qml); - person PsiX; 14.07.2016
comment
это не имеет отношения к вопросу, но да. Проверьте это, поместив Timer в QML (с onTriggered: loader.source = "myqml.qml"), и создайте этот файл во время работы приложения. - person Velkan; 14.07.2016
comment
Обновленный ответ с решением qml. - person PsiX; 14.07.2016